Semaphore(信号量)源码分析

Posted Uncle_Bjorney

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Semaphore(信号量)源码分析相关的知识,希望对你有一定的参考价值。

1. Semaphore

Semaphore和ReentrantReadWriteLock.ReadLock(读锁)都采用AbstractOwnableSynchronizer共享排队的方式实现。

关于AbstractQueuedSynchronizer中的独占锁和共享锁,请参考ReentrantLock(http://www.cnblogs.com/bjorney/p/8040085.html)和ReentrantReadWriteLock(http://www.cnblogs.com/bjorney/p/8064268.html)

问题:Semaphore在acquire时不检查传入的参数是否超过state最大值??? 例如,new Semaphore(5, ture || false) -> acquire(10),则调用acquire的线程将被阻塞
           1)在公平模式下,之后所有调用acquire的线程都将在SyncQueue中排队而永远阻塞???
           2)在非公平模式下,之后所有acquire失败而参与排队的线程都将永远阻塞???

public class Semaphore implements java.io.Serializable {
    private final Sync sync;

    public Semaphore(int permits) {
        sync = new NonfairSync(permits); // 公平竞争,sync的锁状态(锁计数)state = permits
    }

    public Semaphore(int permits, boolean fair) {
        sync = fair ? new FairSync(permits) : new NonfairSync(permits); // 公平竞争 || 非公平竞争
    }

    public void acquire() throws InterruptedException; // acquire(1)
    public void acquire(int permits) throws InterruptedException { // permits必须>=0
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireSharedInterruptibly(permits);
    }

    public void acquireUninterruptibly(); // acquireUninterruptibly(1)
    public void acquireUninterruptibly(int permits) { // permits必须>=0
        if (permits < 0) throw new IllegalArgumentException();
        sync.acquireShared(permits);
    }

    public boolean tryAcquire(); // tryAcquire(1)
    public boolean tryAcquire(int permits) { // permits必须>=0
        if (permits < 0) throw new IllegalArgumentException();
        return sync.nonfairTryAcquireShared(permits) >= 0;
    }

    public boolean tryAcquire(long timeout, TimeUnit unit); // tryAcquire(1, timeout, unit)
    public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException { // permits必须>=0
        if (permits < 0) throw new IllegalArgumentException();
        return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
    }

    public void release(); // release(1)
    public void release(int permits) { // permits必须>=0
        if (permits < 0) throw new IllegalArgumentException();
        sync.releaseShared(permits);
    }

    ... ...
}

2. Semaphore.Sync

abstract static class Sync extends AbstractQueuedSynchronizer {
    Sync(int permits) {
        setState(permits);
    }

    final int nonfairTryAcquireShared(int acquires) { // 尝试非公平取锁
        for (;;) {
            // CAS(state)失败将回到此处
            int available = getState();                                                      /*记录state*/
            int remaining = available - acquires;
            if (remaining < 0 || compareAndSetState(available, remaining)) //remaining >= 0时/*CAS设置state -= acquires*/
                return remaining; // remaining < 0:SyncQueue中排队
        }
    }

    protected final boolean tryReleaseShared(int releases) {
        for (;;) {
            // CAS(state)失败将回到此处
            int current = getState();               /*记录state*/
            int next = current + releases;
            if (next < current) throw new Error("Maximum permit count exceeded");
            if (compareAndSetState(current, next)) /*CAS设置state += releases*/
                return true;
        }
    }

    ... ...
}

static final class NonfairSync extends Sync {
    NonfairSync(int permits) {
        super(permits);
    }

    protected int tryAcquireShared(int acquires) { // 尝试非公平取锁
        return nonfairTryAcquireShared(acquires);
    }
}

static final class FairSync extends Sync {
    FairSync(int permits) {
        super(permits);
    }

    protected int tryAcquireShared(int acquires) { // 尝试公平取锁
        for (;;) {
            // CAS(state)失败将回到此处
            if (hasQueuedPredecessors()) // SyncQueue不为空 && SyncQueue中下个待唤醒节点非当前线程所在节点
                return -1; // 
            int available = getState();                                                      /*记录state*/
            int remaining = available - acquires;
            if (remaining < 0 || compareAndSetState(available, remaining)) //remaining >= 0时/*CAS设置state -= acquires*/
                return remaining;
        }
    }
}

以上是关于Semaphore(信号量)源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核源码分析 -- 同步原语 -- 信号量 semaphore

Linux内核源码分析 -- 同步原语 -- 信号量 semaphore

Semaphore 源码分析

Java并发编程之Semaphore信号量源码分析

Semaphore源码分析

Semaphore源码分析