带着问题看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 阅读(276) 评论(0) 编辑 收藏 举报