Lock方法执行调用直接获取锁(非公平锁没有该步骤),获取不到执行sync.lock();由于公平参数决定创建的是FailLock是NonFailSync.这个时候就会调用具体实现的lock(Sync中是抽象)方法. 调用acquire(1)方法(Sync中抽象方法) 该方法中调用AQS中的tryAcquire方法(抽象方法),最终调用实现类的tryAcquire方法.
锁获取逻辑:
1.判读是否是head的后继节点(head中不存在Thread).如果是则尝试获取锁.成功退出否则进行第2步(非公平锁没有后继节点的判断)
2.调用addWaiter进行入队操作.根据Thread创建一个Node,Cas尝试入队,失败后调用snq方法(该方法返回该节点的前一个节点,在ReentrantLock中没有使用该返回值)进行自旋入队.
3. 返回入队后的Node再次判断是否是head的后继节点,是则尝试加锁,不是或尝试加锁失败.进行4阻塞判断
4.
(1)如果前一个节点是正常的节点(SINGAL),返回true进行否则进行(2) (2)判断前继节点是否是取消状态,如果是,循环删除取消状态的节点,并将prev指向上上个节点.直至前继节点是有效的节点(目的是增加后继遍历的性能) 如果不是,尝试让自己成为当前锁的竞争者(只有一个). 返回false 结束
5.调用Unsafe park方法进行阻塞 锁解除逻辑: 1.尝试释放锁,如果当前线程不是锁的owner报monitor异常.否则进行第2步 2.判断是否锁已经释放完成(可重入锁,加了几次就要释放几次),否返回.是则进行第3步 3.释放head的后续节点(unsafe unpark方法),
(1)如果后续节点是不是取消状态的节点,唤醒
(2)否则则从尾部向前遍历最前面的状态小于0的节点并唤醒——为什么有这部分 因为如果获取锁的过程异常,lock方法finnal语句块中将执行canncelAcquire操作.将改节点从队列中摘除.摘除是后继node指向自身,前继node的后继node指向下一个正常状态的node.没有动自己的前继node指向,所以从后向前遍历是可以保证顺序的.
ReentrantLock代码逻辑
最新推荐文章于 2023-03-24 14:16:04 发布