深入理解Java并发框架AQS系列(四):共享锁(Shared Lock) (3)

整个流转过程有bug吗?我们设想如下场景:共享锁的并发度设置为1,A、B两个线程同时进入加锁逻辑,B线程成功抢到锁,并开始进入同步块,A线程抢锁失败,准备挂到阻塞队列,正常流程是A线程将ws由0修改为-1后,进入挂起状态,但B线程执行较快,已经优先A线程并开始执行解锁逻辑,将ws由0修改为了-3,然后B线程正常结束;A线程发现ws为-3后,将其修改为-1,然后进入挂起。 如果这个场景真实发生的话,A线程将永久处于挂起状态,那岂不是存在漏洞?

然而事实并非如此,因为只要A线程将ws修改为-1后,都要再尝试进行一次获取锁的操作,正是这个操作避免了上述情况的发生,可见aqs是很严谨的

共享锁加入阻塞队列及解锁ws流转示意图

3.3、保证并发度

阻塞队列中节点的激活顺序是什么样呢?其实激活顺序3.2章节已经描述的较为清楚,解锁的逻辑只负责激活头节点,那如何保证共享锁的并发度?

我们还是假定这样一个场景:共享锁的并发度为5,阻塞队列中有20个节点,只有head节点已被唤醒,且没有新的请求进入,我们希望在同一时刻,同时有5个节点处于激活状态。针对上述场景,aqs如何做到呢?

共享锁阻塞队列并发度

其实head节点被激活时,在第一时间会通知后续节点,并将其唤醒,然后才会执行同步块逻辑,保证了等待中的节点快速激活

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzgsdj.html