ReentrantLock源码研读

昨天没发成功

继续整理这几天读的源码 

ReentrantLock是AQS的一个实现,让我们看看它的源码

其有三个内部类Sync,NonfairSync,FairSync,后面两个继承了Sync,Sync继承了AQS。后面二者是真正工作的类,NonfairSync用于非公平锁,FairSync用于公平锁,这二者除了tryAcquire方法外都使用Sync的方法实现,我们先看看Sync

首先是这个nonfairTryAcquire,逻辑很简单,如果当前state是0即锁空闲,则CAS加锁,成功后使用setExclusiveOwnerThread设置当前占有锁的线程为current;如果当前线程是占有锁的线程,则将state加1,表示重入了;否则获取失败

这里再说一下setExclusiveOwnerThread和getExclusiveOwnerThread两个方法,这两个方法来自AbstractOwnableSynchronizer,这个类是AQS的父类,用途就是设置和得到当前正在使用资源的线程

这里可以注意一下,上图中else if语句块中没有任何保证并发安全的措施,因为其判断条件中 current == getExclusiveOwnerThread()已经保证了只有使用资源的那一个线程可以进入这个语句块,所以天生就是并发安全的。这是不是为我们提供了另一个无锁并发安全的思维

tryRelease方法也非常简单,如果不是持有锁的线程调用此方法直接抛出异常。state自减一,如果为0则说明释放成功, setExclusiveOwnerThread(null)表明没有线程此时持有锁;不为0则释放失败,因为有重入锁还未释放

Sync到这里就结束了,来看看NonfairSync

可以看到直接调用了nonfairTryAcquire,因为AQS本身就是不公平的,记得AQS源码中调用acquire方法时会先试图竞争一次资源,哪怕此时队列中还有别的线程早就等待了。所以AQS不需要做任何操作就天生不公平了

现在来看看FairSync怎么保证公平性 

其实可以看到,只有被选中的部分和非公平锁实现不一样。其中用到了一个hasQueuePredecessors,来看一下,这个方法是AQS提供的

可以看到这个方法执行到最后的if判断时,s应该是队列中最前面的未被cancel的节点(除头节点外的最前面),然后判断s是否和当前线程一致,如果一致返回false,不一致返回true

然后继续看上面的tryAcquire,可以看到如果当前线程是最早等待的线程,且锁可用,且CAS成功则返回true

如果当前线程已经占有了锁,hasQueuePredecessors中s代表的线程则不会和当前线程一致(因为h是当前线程节点,而for循环中判断 p!=h),会返回true。这样tryAcquire会进入else if设置重入锁,和我们的逻辑一致

ReentrantLock的lock直接使用了acquire,unlock直接使用了release这都没什么好说

此外ReentrantLock的trylock是非公平锁的实现,可以看到直接使用了nonfairTryAcquire,不管当前ReentrantLock是否公平其都是非公平的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值