ReentrantLock的非公平锁和公平锁的实现原理

本文详细分析了ReentrantLock中的非公平锁与公平锁的实现原理。重点介绍了NonfairSync和FairSync内部类的tryAcquire方法,解释了线程如何获取锁及释放锁的过程。并通过对比非公平锁与公平锁的区别,说明了公平锁如何确保线程获取锁的公平性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

非公平锁

因为之前已经分析过AQS,ReentranLock是利用一个实现了AQS的NonfairSync来获取非公平锁。所以只需关注NonfairSync的tryAcquire的实现。

 

 

 

获取(nonfairTryAcquire方法定义在Sync内部类中)

 

获取锁成功分为两种情况,第一个if判断AQS的state是否等于0,表示锁没有人占有。接着,hasQueuedPredecessors判断队列是否有排在前面的线程在等待锁,没有的话调用compareAndSetState使用CAS(Unsafe类调用本地方法)的方式修改state,传入的acquires写死是1。最后线程获取锁成功,setExclusiveOwnerThread将线程记录为独占锁的线程

第二个if判断当前线程是否为独占锁的线程,因为ReentrantLock是可重入的,线程可以不停地lock来增加state的值,对应地需要unlock来解锁,直到state为零。

 

释放锁tryRelease方法定义在Sync内部类中)

通过上面详细的获取锁过程分析,释放锁过程大概可以猜到:头节点是获取锁的线程,先移出队列,再通知后面的节点获取锁。

 

因为锁是可以重入的,所以每次lock会让state加1,对应地每次unlock要让state减1,直到为0时将独占线程变量设置为空,返回标记是否彻底释放锁。

 

公平锁的实现

FairSync的源码如下:

 

与nonfairAcquire()方法相比,唯一的不同之处在于FairSync多了hasQueuedPredecessors()(由AQS提供)方法:

 

其作用是判断:是否存在比当前线程等待锁时间更长的线程,有就返回true,没有就返回false。 通过判断当前线程在队列中的位置,(比较难理解的是h!=t&&(s=h.next)==null这一条件是代表什么?)

也就是说每次获取锁都需要判断队列中是否还有排在前面的线程,若不存在才能继续获取锁!!,若队列还存在等待线程则获取失败,当前线程进入队列尾部。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值