菜鸡每日一面系列打卡16天
每天一道面试题目
助力小伙伴轻松拿offer
坚持就是胜利,我们一起努力!
题目描述
谈谈你对ReentrantLock的理解。
题目分析
在上一篇有关synchronized关键字的总结中,菜鸡曾提到过,互斥同步不仅可以通过synchronized关键字保证,还可以通过Lock接口保证。
不同于synchronized的JVM内置锁,Lock接口是类库层面的锁,相较于synchronized关键字来说,使用Lock接口实现同步有更大的操作空间,可以更好地应对更多复杂的场景。
本文要说的ReentrantLock就是Lock接口最常见的一种实现。在面试过程中,虽然出现频率不及synchronized关键字,但也算是面试过程中的常客,而且可考查的知识点相对来说比较多,其重要性也就不言而喻了。
接下来,随菜鸡一起去看看吧。
题目解答
01
概述
顾名思义,ReentrantLock是重入锁。它实现了Lock接口,是基于AQS(一种用于构建同步器的框架,后续会讲到)构造出来的一种同步器。
02
功能
同synchronized一样,ReentrantLock也是可重入的,与synchronized相比增加了一些高级功能,主要有以下三项:等待可中断、可实现公平锁、锁可以绑定多个条件。
等待可中断:是指当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。可中断特性对处理执行时间非常长的同步块很有帮助。
公平锁:是指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁;而非公平锁则不保证这一点,在锁被释放时,任何一个等待锁的线程都有机会获得锁。synchronized中的锁是非公平的,ReentrantLock在默认情况下也是非公平的,但可以通过带布尔值的构造函数要求使用公平锁。不过一旦使用了公平锁,将会导致ReentrantLock的性能急剧下降,会明显影响吞吐量。
锁绑定多个条件:是指一个ReentrantLock对象可以同时绑定多个Condition对象。在synchronized中,锁对象的wait()跟它的notify()或者notifyAll()方法配合可以实现一个隐含的条件,如果要和多于一个的条件关联的时候,就不得不额外添加一个锁;而ReentrantLock则无须这样做,多次调用newCondition()方法即可。
值得注意的是,听起来好像觉得ReentrantLock无所不能,分分钟把synchronized秒成渣渣,然而并不是这样的,其实synchronized关键字有其特有的优势:
使用简单,不易出错。
经过JVM底层的锁优化之后,二者的性能相差不大。
JVM可以在线程和对象的元数据中记录synchronized中锁的相关信息,而如果使用ReentrantLock,JVM很难得知具体哪些锁对象是由特定线程所持有的。
03
整体结构
说了这么多,来看一下ReentrantLock的整体结构。
图中所示的FairSync即为ReentrantLock的公平锁实现,而NonfairSync为非公平锁实现。二者都继承了名为Sync的内部类,至于细节是如何实现的,这就涉及到了神奇的AQS模板类了,后续将会针对AQS类进行源码级别的剖析,届时一切谜底将被揭开。
以上便是菜鸡对ReentrantLock的一些总结,供大家参考。
参考资料
《深入理解Java虚拟机》周志明著
《Java并发编程实战》Brian Goetz等著
学习 | 工作 | 分享
????长按关注“有理想的菜鸡”
只有你想不到,没有你学不到