AbstractQueuedSynchronizer

AQS中获取操作和释放操作的标准形式:

boolean acquire() throws InterruptedException{
    while(当前状态不允许获取操作){
        if(需要阻塞获取请求){
            如果当前线程不在队列中,则将其插入队列
            阻塞当前线程
        }
        else
            返回失败
    }
    可能更新同步器的状态
    如果线程位与队列中,则将其移出队列
    返回成功
}

void release(){
    更新同步器的状态
    if(新的状态允许某个被阻塞的线程获取成功)
        解除队列中一个或多个线程的阻塞状态
}

 如果某个同步器支持独占的获取操作,那么需要实现一些保护方法,包括tryAcquire、tryRelease和isHeldExclusively等,而对于支持共享获取的同步器,则应该实现tryAcquireShared和tryReleaseShared等方法。AQS中的acquire、acquireShared、release和releaseShared等方法都将调用这些方法在子类中带有前缀try的版本来判断某个操作是否能执行。在同步器的子类中,可以根据其获取操作和释放操作的语义,使用getState、setState以及compareAndSetState来检查和更新状态,并通过返回的状态值来告知基类“获取”或“释放”同步器的操作是否成功。

使用AQS实现的二元闭锁

@ThreadSafe
public class OneShotLatch {
    private final Sync sync = new Sync();

    public void signal() {
        sync.releaseShared(0);
    }

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(0);
    }

    private class Sync extends AbstractQueuedSynchronizer {
        protected int tryAcquireShared(int ignored) {
            // Succeed if latch is open (state == 1), else fail
            return (getState() == 1) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int ignored) {
            setState(1); // Latch is now open
            return true; // Other threads may now be able to acquire

        }
    }
}

 在OneShotLatch中,AQS状态用来表示闭锁状态–关闭(0)或者打开(1)。await方法调用AQS的acquireSharedInterruptibly,然后接着调用OneShotLatch中的tryAcquireShared方法。在tryAcquireShared的实现中必须返回一个值来表示该获取操作能否执行。如果之前已经打开了闭锁,那么tryAcquireShared将返回成功并允许线程通过,否则就会返回一个表示获取操作失败的值。acquireSharedInterruptibly方法在处理失败的方式,是把这个线程放入等待线程队列中。类似的,signal将调用releaseShared,接下来又会调用tryReleaseShared。在tryReleaseShared中将无条件地吧闭锁的状态设置为打开,(通过返回值)表示该同步器处于完全被释放的状态。因而AQS让所有等待中的线程都尝试重新请求该同步器,并且由于tryAcquireShared将返回成功,因此现在的请求操作都将成功。

猜你喜欢

转载自blog.csdn.net/u014653854/article/details/80724163
今日推荐