AQS.doReleaseShared

共享锁的释放和独占锁的释放有一定的差别

前面唤醒锁的逻辑和独占锁是一样,先判断头结点是不是SIGNAL状态,如果是,则修改为0,并且唤醒头结点的下一个节点

PROPAGATE: 标识为PROPAGATE状态的节点,是共享锁模式下的节点状态,处于这个状态下的节点,会对线程的唤醒进行传播

private void doReleaseShared() { 
	for (;;) { 
		Node h = head; 
		if (h != null && h != tail) 
		{ 
			int ws = h.waitStatus; 
			if (ws == Node.SIGNAL) { 
				if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) 
				continue; 
				// loop to recheck cases 
				unparkSuccessor(h); 
			} 

			// 这个 CAS 失败的场景是:执行到这里的时候,刚好有一个节点入队,入队会将这个 ws 设置为 -1 
			else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) 
			continue; 
			// loop on failed CAS 
		} 
		// 如果到这里的时候,前面唤醒的线程已经占领了 head,那么再循环
		// 通过检查头节点是否改变了,如果
		改变了就继续循环 
		if (h == head) 
		// loop if head changed 
		break; 
	} 
} 

h == head:说明头节点还没有被刚刚用 unparkSuccessor 唤醒的线程(这里可以理解为 ThreadB)占有,此时 break 退出循环。

h != head:头节点被刚刚唤醒的线程(这里可以理解为 ThreadB)占有,那么这里重新进入下一轮循环,唤醒下一个节点(这里是 ThreadB )。我们知道,等到 ThreadB 被唤醒后,其实是会主动唤醒 ThreadC...

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值