AQS理解之六,AQS的其他实现类

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/doujinlong1/article/details/84938680

AQS理解之六,AQS的其他实现类

1,ThreadPoolExecutor 中的 Worker 类

protected boolean tryAcquire(int unused) {
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }

    protected boolean tryRelease(int unused) {
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }

    public void lock()        { acquire(1); }
    public boolean tryLock()  { return tryAcquire(1); }
    public void unlock()      { release(1); }
    public boolean isLocked() { return isHeldExclusively(); }

重写了这几个方法,可以看出来实现的是一个不可重入的锁。

2,Semaphore 信号量类

abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 1192457210091910933L;

    Sync(int permits) {
        setState(permits);
    }

    final int getPermits() {
        return getState();
    }

    final int nonfairTryAcquireShared(int acquires) {
        for (;;) {
            int available = getState();
            int remaining = available - acquires;
            if (remaining < 0 ||
                compareAndSetState(available, remaining))
                return remaining;
        }
    }

    protected final boolean tryReleaseShared(int releases) {
        for (;;) {
            int current = getState();
            int next = current + releases;
            if (next < current) // overflow
                throw new Error("Maximum permit count exceeded");
            if (compareAndSetState(current, next))
                return true;
        }
    }

    final void reducePermits(int reductions) {
        for (;;) {
            int current = getState();
            int next = current - reductions;
            if (next > current) // underflow
                throw new Error("Permit count underflow");
            if (compareAndSetState(current, next))
                return;
        }
    }

    final int drainPermits() {
        for (;;) {
            int current = getState();
            if (current == 0 || compareAndSetState(current, 0))
                return current;
        }
    }
}

使用state的数量来代表信号量已经使用的数,如果大于0,则可以进入,如果小于等于0,则阻塞住,不能获取到信号量。

和ReentrantLock有点类似,如果acquire时不能进入,则阻塞,并加入链表,在release时会将阻塞的节点unpark打开。

3,CountDownLatch

首先看下CountDownLatch的构造使用

CountDownLatch countDownLatch = new CountDownLatch(5);//构造
countDownLatch.countDown();//计数
countDownLatch.await();//等待完成
//构造时,实际上是设置了state为一个数。
Sync(int count) {
        setState(count);
}
//这里实际上就是一个release操作,每次都会将state原子性减一,并顺便会将阻塞的节点unpark打开。
public final boolean releaseShared(int arg) {
    if (tryReleaseShared(arg)) {
        doReleaseShared();
        return true;
    }
    return false;
}

protected boolean tryReleaseShared(int releases) {
        // Decrement count; signal when transition to zero
        for (;;) {
            int c = getState();
            if (c == 0)
                return false;
            int nextc = c-1;
            if (compareAndSetState(c, nextc))
                return nextc == 0;
        }
    }

//await方法实际上是计算state是否为0,如果不为0,则park阻塞等待直到为0
public final void acquireSharedInterruptibly(int arg)
        throws InterruptedException {
    if (Thread.interrupted())
        throw new InterruptedException();
    if (tryAcquireShared(arg) < 0)
        doAcquireSharedInterruptibly(arg);
}


protected int tryAcquireShared(int acquires) {
        return (getState() == 0) ? 1 : -1;
    }

使用state表示仍需要执行的次数,当为0时结束阻塞

总结

AQS实现了一套公共的实现Java锁的逻辑,我们可以继承它来实现自己在多线程下的锁。

展开阅读全文

没有更多推荐了,返回首页