共享式同步状态获取与释放

共享式获取与独占式获取最主要的区别在于同一时刻能否有多个线程同时获取到同步状态。以文件的读写为例,若一个程序在对文件进行读操作,那么这一时刻对于该文件的写操作均被阻塞,而读操作能够同时进行。写操作要求对资源的独占式访问,而读操作可以是共享式访问,两种不同的访问模式在同一时刻对文件或资源的访问情况,如下图所示。
共享式与独占式访问资源对比
在上图中左半部分,共享式访问资源时,其他共享式的访问均被允许,而独占式访问被阻塞,右半部分是独占式访问资源时,同一时刻其他访问均被阻塞。
通过调用同步器的acquireShared(int arg)方法可以共享式地获取同步状态,该方法代码如下:

public final void acquireShared(int arg){
    if(tryAcquireShared(arg) <0)
        doAcquireShared(arg);
}
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 ){
                int r=tryAcquireShared(arg);
                if(r>0){
                    setHeadAndPropagate(node,r);
                    p.next=null;//help GC
                    if (interrupted)
                        selfInterrupt();
                        failed=false;
                        return;
                }
            }
            if()shouldParkAfterFailedAcquire(p,node) && parkAndCheckInterrupt())
                interrupted=true;
        }
    }finally{
        if (failed)
            cancelAcquire(node);
    }
}

在acquireShared(int arg)方法中,同步器调用tryAcquireShared(int arg)方法尝试获取同步tryAcquireShared(int arg)方法返回值为int类型,当返回值大于等于0时,表示能够获取到同步状态。因此,在共享式获取的自旋过程中,成功获取到同步状态并退出自旋的条件就是tryAcquireShared(int arg)方法返回值大于等于0。可以看到,在doAcquireShared(int arg)方法的自旋过程中,如果当前节点的前驱为头节点时,尝试获取同步状态,如果返回值大于等于0,表示该次获取同步状态成功并从自旋过程中退出。
共享式获取需要释放同步状态,通过调用releaseShared(int arg)方法可以释放同步状态,该方法代码如下所示。

public final boolean releaseShared(int arg){
    if(tryReleaseShared(arg)){
        doReleaseShared();
        return true;
    }
    return false;
}

该方法在释放同步状态之后,将会唤醒后续处于等待状态的节点。对于能够支持多个线程同时访问的并发组件(比如Semaphore),它和独占式主要区别在于tryReleaseShared(int arg)方法必须确保同步状态(或者资源数)线程安全释放,一般是通过循环和CAS来保证的,因为释放同步状态的操作会同时来自多个线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值