Semaphore是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理使用公共资源。
可以用于流量控制,特别是公用资源有限的应用场景,比如数据库连接。
Semaphore的用法很简单,首先线程使用acquire()方法获取一个许可证,使用完之后调用release()方法归还许可证。还可以用tryAcquire()方法尝试获取许可证。
acquire()方法最后的实现逻辑分公平锁和非公平锁
//公平锁的获取方式
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;
}
}
//不公平锁的获取方式,区别就在于不再判断是否有线程在等待,而是直接尝试获取许可
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;
}
}
其他一些方法:
int availablePermits();返回此信号量中当前可用的许可证数
int getQueueLength();返回正在等待获取许可证的线程数
Boolean hasQueuedThreads();是否有线程正在等待获取许可证
void reducePermits();减少reduction个许可证,是protected方法
collection getQueuedThreads();返回所有等待获取许可证的线程集合,是个protected方法