Synchronized与ReentrantLock

Synchronized与ReentrantLock

从java锁的类型来说,阻塞对应的就是悲观锁,自旋对应的就是乐观锁。在java中乐观锁主要的实现方式就是CAS操作.

相同点:

1、两者都是加锁方式同步,都是阻塞式的同步,如果一个线程获得了锁,其他访问该同步块的线程都必须阻塞在同步块外等待,而进行线程的阻塞和唤醒的代价很高,需要用户态和内核态的切换(因为线程的调度是在内核态进行,也就是通过操作系统)

2、都是可重入锁,同一个线程再次获得锁不会出现死锁,每进入一次,锁计数器自增1。计数器下降到0才能释放锁。

 

不同点:

1、Synchronized使用简便无需手动释放锁,ReentrantLock需要手动释放。

2、Synchronized是JAVA关键字,依赖JVM实现,ReentrankLock是依赖JDK实现的,可读源码。

3、Synchronized是不可中断(原子性),其他线程必须等待获得锁的线程执行完才能进行锁争夺。ReentrankLock可以手动中断当前正在等待获取锁的线程(lockInterruptibly),如等待时间太久仍获取不到锁,则可手动中断。

4、Synchronized、ReentrantLock默认都是不公平锁,ReentrantLock可以设置成公平锁。

5、ReentrantLock锁粒度比synchronized小,锁可以绑定多个条件Condition,可以singnal精确分组唤醒线程。Synchronized只能随机唤醒一个或全部。

6、Synchronized是基于Monitor实现的,ReentrantLock是基于AQS(AbstractQueuedSynchronizer)和LockSupport,通过CAS自旋实现的。

 7、因为每个对象只有一个monitor,所以synchronized只能被一个线程占有。而lock没有这个限制。比ReentrantReadWriteLock可以同时被多个线程持有读锁。

 

Synchronized

修饰同步代码块加锁,会插入monitorenter和monitorexit两个指令

修饰同步方法时会有ACC_SYNCHRONIZED 标识。

 

建议:

1、从效率考虑: Java在包java.util.concurrent下为我们提供了很多的并发类,如果使用的话首先考虑使用这些类(前提是足够了解这些类),比如考虑ConcurrentHashMap等替换HashMap。

2、安全性上考虑: 因为synchronized使用简单,而且虚拟机内置帮我们处理了解锁的操作,就算是异常情况下也会解锁,所以从编码上来看的话,synchronized比Lock更加安全(因为Lock可能会忘记在finally中解锁)。

3、从灵活性上考虑: Lock有更多的API可供更复杂的需求选择,如果你需要比如超时功能,可以考虑使用Lock。

你可能感兴趣的:(积累,分享,java,并发编程)