带着问题看AQS waitState 系列一

AQS中存在设置waitState状态的方法 shouldParkAfterFailedAcquire , 根据问题反推其设计的原因

 

 shouldParkAfterFailedAcquire源码如下

 

 

 

以ReentrantLock为例子

 

问题

ReentrantLock进行unlock时,源码如下

 

 

 AQS根据waitStatus进行队列中线程的唤醒,waitStatus初始值为0,

在ReentrantLock中,若waitStatus为-1,则标识后续的一个线程是需要被唤醒的线程

 

假设一种场景,两个线程并发执行,第一个线程T1先执行,获取到了锁,第二个线程T2后执行,T2执行到了shouldParkAfterFailedAcquire时,cpu调度时间用完,停止运行;T1进行unLock

根据unLock源码,T1直接执行完,不会进行unparkSuccessor(h),也就没有对T2进行unpark。

 

 

 

 此时若T2再次获得执行机会,进行shouldParkAfterFailedAcquire ,则设置前一个节点waitStatus为-1,及运行compareAndSetWaitStatus ,最终返回false

 

 

 再看 shouldParkAfterFailedAcquire被调用的地方

 

 此时返回false,循环继续,发现T2的前一个节点是头节点,进行tryAcquire。

若是公平锁,必然会获取锁成功。

若是非公平锁,存在获取锁失败的情况,再次调用shouldParkAfterFailedAcquire,返回true,进行调用 parkAndCheckInterrupt,及进行park操作

 

 

综述,shouldParkAfterFailedAcquire在compareAndSetWaitStatus为什么返回false,就比较明朗了,要是获取到锁的线程,没有对head后面的线程进行unpark操作,则该线程通过自旋,自己再次尝试获取锁

posted on 2022-08-14 11:49  xingshouzhan  阅读(267)  评论(0编辑  收藏  举报

导航