ReentrantLock实现原理

  • ReentrantLock是基于AQS实现的可重入锁,比synchronized更灵活,可以设置超时时间,可以中断,支持公平和非公平锁两种方式。
  • 公平锁获取锁的方式:
    • 主要就是这三步

  • 第一步:tryAcquire 先尝试获得锁
    • 先获取state,情况一:如果state=0,那么说明当前没有线程占着锁,如果当前线程不需要排队,那么就可以尝试CAS修改state的状态,如果CAS修改成功,就说明抢锁成功,就把setExclusiveOwnerThread设置成当前线程。程序到这里就结束啦~
      • hasQueuedPredecessors()判定是否需要排队。官方解释,如果队列中有线程排在你前面,那你就需要排队;否则当前线程就在队列的头的位置,或者队列是空的,你就可以起CAS抢锁。保证了公平性!!!

  • 情况二:如果获得state!=0,但是被自己(当前线程占用),可以直接把state加1。程序到这里就结束啦~
  • 其他情况:都认为尝试获取锁失败。那就要走第二步。
  • 第二步:addWaiter 把当前线程当作节点,放到等待队列的尾部
  • 第三步:acquireQueued  无限循环执行排队操作,也就是阻塞线程,直到获得锁
    • 如果当前线程已经排在队列头部,就尝试获得锁。获得成功程序到这就结束啦~
    • 如果没有获得锁,就执行shouldParkAfterFailedAcquire ,如果排在当前线程前面的节点状态是signal,就返回true;如果排在前面的节点是CANCELLED,把前面等待状态是CANCELLED的全部清理掉,并把当前线程的前一节点设置成signal状态,就返回false(注意这里是无限循环,下次循环就会返回true);
      • 这里返回false的好处是当前线程不需要立刻进入等待状态,可以等其他条件变化后,再判断是否进行等待状态。其次返回false,也不需要走后面的park方法啦
    • 总之,这一步就是阻塞当前线程,排队等待,直到自己排到队首。
    • 那么问题来了,我怎么能排到队首?当一个线程释放锁的时候,它会将当前头节点的下一个等待节点设置为新的头节点,并且唤醒这个新的头节点。
  • 总结:公平锁lock的步骤简单讲就是,如果你不需要排队尝试获得锁,否则就排队阻塞直到获得锁。
  • 非公平锁
    • 非公平锁在一开始比公平锁多了一步CAS抢锁的步骤。通俗讲可以插队。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值