AQS源码解读(六)——从PROPAGATE和setHeadAndPropagate()分析共享锁的传播性

本文详细解释了Java并发编程中`acquireShared`方法的工作原理,特别是共享锁的传播性,涉及ReentrantReadWriteLock和Semaphore的实现,以及doAcquireShared方法如何在同步队列中操作。文章通过例子展示了共享锁传播性在多线程环境中的作用和必要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

三、acquireShared获取共享锁


共享锁除了可以多个线程共享外,在共享节点间还具有传播性。何为传播性,先看共享锁获取锁的代码:

//java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireShared

public final void acquireShared(int arg) {

//tryAcquireShared 返回-1获取锁失败,返回值大于1或者0获取锁成功

if (tryAcquireShared(arg) < 0)

//获取锁失败,进入队列操作

doAcquireShared(arg);

}

tryAcquireSharedReentrantReadWriteLock中的实现,返回值只有两种,1表示获取锁成功,-1表示获取锁失败。在SemaphoretryAcquireShared的返回值代表资源剩余量,返回值大于等于0表示获取锁成功,小于0表示获取锁失败。

四、doAcquireShared进入同步队列操作


tryAcquireShared获取锁失败后,进入AQS同步队列操作doAcquireShared。创建共享节点node,并CAS排到队列尾部,接下来判断是应该阻塞还是继续获取锁。当node的前驱节点是head时,尝试获取锁tryAcquireShared,如果获取锁成功返回值r >= 0,则执行函数setHeadAndPropagate,这个函数就是共享锁的传播性。

//java.util.concurrent.locks.AbstractQueuedSynchronizer#doAcquireShared

private void doAcquireShared(int arg) {

//创建一个读节点,并入队列

final Node node = addWaiter(Node.SHARED);

boolean failed = true;

try {

boolean interrupted = false;

for (;😉 {

final Node p = node.predecessor();

if (p == head) {

//如果前继节点是head,则尝试获取锁

int r = tryAcquireShared(arg);

if (r >= 0) {

//获取锁成功,设置新head和共享传播(唤醒后继共享节点)

setHeadAndPropagate(node, r);

p.next = null; // help GC

if (interrupted)

selfInterrupt();

failed = false;

return;

}

}

/**

  • p不是头结点 or 获取锁失败,判断是否应该被阻塞

  • 前继节点的ws = SIGNAL 时应该被阻塞

*/

if (shouldParkAfterFailedAcquire(p, node) &&

parkAndCheckInterrupt())

interrupted = true;

}

} finally {

if (failed)

cancelAcquire(node);

}

}

五、setHeadAndPropagate共享锁的传播性


node获取锁成功出队,设置新head,并将共享性传播给后继节点,即唤醒后继共享节点。为什么当一个节点的线程获取共享锁后,要唤醒后继共享节点?共享锁是可以多个线程共有的,当一个节点的线程获取共享锁后,必然要通知后继共享节点的线程,也可以获取锁了,这样就不会让其他等待的线程等很久,而传播性的目的也是尽快通知其他等待的线程尽快获取锁。

private void setH

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值