关于共享锁中doReleaseShared()理解

关于共享锁中doReleaseShared()理解

public final boolean releaseShared(int arg) {
	//同一时刻只允许一个线程进入doReleaseShared()方法
	if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

理想情况下唤醒这个节点后面所有的线程。

private void doReleaseShared() {
    for (;;) {
        Node h = head;
        if (h != null && h != tail) {
            int ws = h.waitStatus;
            //这里说明了头节点后面是有节点的,需要被唤醒。
            if (ws == Node.SIGNAL) {
         		//这里更新失败,是因为会出现并发情况,因为刚唤醒的线程也会调用doReleaseShared()所以此时是有多个线程同时执行这个方法。
                if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
                    continue;            // loop to recheck cases
                unparkSuccessor(h);
            }
            //head.waitStatus=0的情况有两种
            //1、就是head节点没有及时更新,线程被唤醒之后获取到了锁,在更新head之前,又经过一轮循环执行到这。  但是如果节点没有及时更新就会退出。所以执行到这一步只可能是情况2
            //2、head节点及时更新了,但是到了最后一个节点,它的head.waitStatus=0
            else if (ws == 0 &&
                     !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
                continue;                // loop on failed CAS
        }
        //节点没有及时更新,就退出。
        if (h == head)                   // loop if head changed
            break;
    }
}

所以说整体的逻辑就是在head能及时更新的情况下,唤醒队列中所有的节点,直到队列中只有head。
并将这个head设置为compareAndSetWaitStatus(h, 0, Node.PROPAGATE)
然后通过下面代码退出。

if (h == head)                   // loop if head changed
     break;

那什么时候compareAndSetWaitStatus(h, 0, Node.PROPAGATE)修改会失败呢?
就是当ws==0判断后面的一瞬间又有新的节点加入然后将head的值又改为-1,然后执行continue又会将刚加入的节点给唤醒。

else if (ws == 0 &&!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
      continue;      

所以以上代码是尽可能的将所有的节点给唤醒,而唤醒的线程又会帮助去唤醒线程,包括新加入的节点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值