首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java Concurrent Semaphore

前言

Semaphore一种通常用于维持数量的信号量工具,在Java 并发中最常见的使用就是维持并发线程的个数,正如之前提到的,并不是并发场景线程越多越好,应该是跟对应的业务场景及CPU数量共同决定。而需要维持数量时,我们大致就需要一个JUC里面Semaphore这样一个信号量工具。Semaphore 同样依赖于AQS实现(shared),内部持有一个Sync对象,同样存在公平实现、非公平实现两种模式(可以在构造时指定fair参数)。

原理

每次线程执行前夕都会从这里默认通过一下许可,然后执行完毕时释放一下许可,根据维系的数量来决定当前线程是该等待还是执行。 简单看一下源码,实现蛮简单的 首先是持有AQS对象

代码语言:javascript
复制
public class Semaphore implements java.io.Serializable {
    private static final long serialVersionUID = -3222578661600680210L;
    /** All mechanics via AbstractQueuedSynchronizer subclass */
    private final Sync sync;

取许可及释放操作

代码语言:javascript
复制
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;
    }
}

公平非公平两种实现版本:

代码语言:javascript
复制
/**
 * NonFair version
 */
static final class NonfairSync extends Sync {
    private static final long serialVersionUID = -2694183684443567898L;
    NonfairSync(int permits) {
        super(permits);
    }
    protected int tryAcquireShared(int acquires) {
        return nonfairTryAcquireShared(acquires);
    }
}
/**
 * Fair version
 */
static final class FairSync extends Sync {
    private static final long serialVersionUID = 2014338818796000944L;
    FairSync(int permits) {
        super(permits);
    }
    protected int tryAcquireShared(int acquires) {
        for (;;) {
            if (hasQueuedPredecessors())
                return -1;
            int available = getState();
            int remaining = available - acquires;
            if (remaining < 0 ||
                compareAndSetState(available, remaining))
                return remaining;
        }
    }
}
下一篇
举报
领券