Semaphore底层原理
Semaphore就是多个线程同时跑直到state变为0则阻塞等待唤醒
Semaphore对外提供两个核心方法,一个是acquire,一个是release,内部继承了AQS的框架,实现了公平模式和非公平模式
- acquire都会调用AQS中公共的acqureSharedInterruptibly
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
//如果返回值小于0,则放入队尾并执行LockSupport的park()方法阻塞等待唤醒
doAcquireSharedInterruptibly(arg);
}
tryAcquireShared在公平和非公平各不相同, doAcquireSharedInterruptibly调用的共同AQS中的方法
doAcquireSharedInterruptibly的实现采用的是AQSCLH隐式双向链表队列,每个Node维护着一个Thread对象,首先将当前Node插入队尾,查看自己优先权,如果前面不是队列头部,并且当前state值是否为0,如果是则唤醒后面节点(每个Node有个next指向下个,调用LockSupport.unpark(next.thread))去唤醒,否则的话执行LockSupport.park(this)阻塞当前线程
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
//队尾不为空
if (pred != null) {
//node的前驱变成tail
node.prev = pred;
//cas将tail设置为当前node
if (compareAndSetTail(pred, node)) {
//pred.就是之前的尾部,下一个指针指向当前node
pred.next = node;
return node;
}
}
//如果是空,执行enq去新建立一个头和尾
enq(node);
return node;
}
private Node enq(final Node node) {
for (;;) {
Node t = tail;
//如果尾是空