JUC.Semaphore

72 阅读1分钟

# JUC.Semaphore

运行一下

public class SemaphoreDemo {

    public static void main(String[] args) {
        Semaphore sem = new Semaphore(2);
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    // 默认使用一个许可.
                    sem.acquire();
                    System.out.println(Thread.currentThread() + " I get it.");
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println(Thread.currentThread() + " I release it.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    sem.release();
                }
            }).start();
        }
    }
}

输出

Thread[Thread-0,5,main] I get it.
Thread[Thread-1,5,main] I get it.
Thread[Thread-1,5,main] I release it.
Thread[Thread-0,5,main] I release it.
Thread[Thread-2,5,main] I get it.
Thread[Thread-2,5,main] I release it.

核心实现

  1. 定义信号量
Semaphore sem = new Semaphore(2);
  1. 获取许可
sem.acquire();

核心原理

定义信号量

public Semaphore(int permits) {
    sync = new NonfairSync(permits);
}
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = -2694183684443567898L;

    NonfairSync(int permits) {
        super(permits);
    }
abstract static class Sync extends AbstractQueuedSynchronizer {
    private static final long serialVersionUID = 1192457210091910933L;

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

获取许可

public void acquire() throws InterruptedException {
    sync.acquireSharedInterruptibly(1);
}
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 nonfairTryAcquireShared(acquires);
}

尝试占用

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

占用

private void doAcquireSharedInterruptibly(int arg)
    throws InterruptedException {
    // 增加共享锁节点
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
        for (;;) {
            final Node p = node.predecessor();
            // 前置头节点
            if (p == head) {
                // cas尝试获取
                int r = tryAcquireShared(arg);
                if (r >= 0) {
                    // 成功则设置头节点,并唤醒传播
                    setHeadAndPropagate(node, r);
                    p.next = null; // help GC
                    failed = false;
                    return;
                }
            }
            // 失败则阻塞线程park,等待唤醒
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                throw new InterruptedException();
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}