Lock 之ReentrantLock

Lock 只定义了 lock, unlock 的接口, 真正起到线程同步作用的为Sync, AQS 的实现类, 主要分析AQS的原理, lock分为 fairLock, nonfairLock
AQS 中维护了state, 是否有线程持有lock, 0: 没有thread 持有锁, 1: thread持有锁, >1: thread 多次获取lock 重入锁, 当lock.lock, 首先尝试compareAndSetState(0, 1)来设置state的状态,
成功说明获锁成功并且setExclusiveOwnerThread(Thread.currentThread()), 如果失败则说明已有thread持有该锁, 调用tryAcquire 继续尝试获取, 公平锁和非公平锁的区别主要在这个方法上,
此处讨论非公平锁, 首先还是尝试compareAndSetState(0, 1) 设置state的状态, 失败查看Thread.currentThread == getExclusiveOwnerThread(), 相等说明是同一个线程再次获取lock,
让state的值+1即可, 如何不是同一线程, 后续步骤主要就是如何让线程进入等待队列和挂起, 创建Node(thread, null) 置于AQS 中维护的Node等待队列 即先入队, 查看当前Node.pre 是否为head, 如果是 tryAcquire()
尝试获取lock,成功setHead(current node) 继续执行thread的任务, node.pre 不是head或者tryAcquire失败 都相当于获取lock失败, 设置node.pre 的waitStatus = -1 (waitStatus可以查看), 源码上的解释是
waitStatus value to indicate successor's thread needs unparking, 个人理解 node.pre.waitStatus = -1 说明当前thread需要被唤醒, 然后挂起当前thread , 通过LockSupport.park,
所以如果在期间调用thread.interrupt thread被终止但不会throw InterruptException, 当lock.unlock释放锁后 (state-1)==0 , unpark head node的下一个node, 挂起的thread被唤醒, 唤醒之后 Thread.interrupted
的状态后续步骤重新设置到thread上, 在唤醒之前的话线程会被终止. lock.unlock 代码比较简单, Thread.currentThread == getExclusiveOwnerThread(), state -1 == 0, setExclusiveOwnerThread(null)
释放锁成功, LockSupport.unpark 等待队列的head.nextNode
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值