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
Lock 之ReentrantLock
最新推荐文章于 2020-06-03 11:13:02 发布