synchronized与ReentrantLock的区别

synchronized与ReentrantLock的区别_第1张图片

在这里插入图片描述
synchronized与ReentrantLock的区别_第2张图片

相同点:
1.都是可重入锁。
2.都保证了可见性与互斥性。
3.都可以用于控制多线程对共享对象的访问。
不同点:
1.来源:
synchronized是java中的关键字,是JVM级别的锁;而ReentrantLock是Lock接口下的一个实现类,是API层面的锁。
2.锁的类型:
synchronized是非公平锁;ReentrantLock支持并可指定非公平锁与公平锁,默认是非公平锁。
3.异常是否释放锁:
synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而ReentrantLock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)
4.相比synchronized,ReentrantLock增加了一些高级功能:
4.1等待可中断。
4.2ReentrantLock可以指定是公平锁还是非公平锁。
4.3用ReentrantLock类结合Condition实例可以实现“选择性通知”。
5.是否知道获取锁:
ReentrantLock可以通过trylock来知道有没有获取锁,而synchronized不能。
6.ReentrantLock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)
7.在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,此时优先使用synchronized;而当竞争资源非常激烈时(即有大量线程同时竞争),此时ReentrantLock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
8.锁机制:
synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。

而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。

现代的CPU提供了指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。

你可能感兴趣的:(多线程与高并发,java,面试,多线程与高并发)