# 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.
核心实现
- 定义信号量
Semaphore sem = new Semaphore(2);
- 获取许可
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);
}
}