Semaphore
计数信号量:控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量,实现某种资源池,对容器施加边界
acquire
步骤同CountDownLatch.wait
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
final int nonfairTryAcquireShared(int acquires) {
//<0才阻塞
for (;;) {
//获取同步状态的值。
int available = getState();
int remaining = available - acquires;
//available为0或者更新成功,直接返回
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
release
public void release() {
sync.releaseShared(1);
}
protected final boolean tryReleaseShared(int releases) {
for (;;) {
//获取同步状态的值。
int current = getState();
//累加
int next = current + releases;
//内存溢出,也就是超过了Integer范围上限
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
//修改值返回
if (compareAndSetState(current, next))
return true;
}
}
总结
与闭锁和其类似,闭锁是为0,才可以访问,信号量恰恰相反,
信号量和闭锁的区别是不是一次性的,可以重复限定多少线程可以访问资源.
如果不限定释放的条件,可以不停的释放从而超过构造设置的许可个数,
建议这样使用
public boolean add(T o) throws InterruptedException {
//阻塞获得许可
sem.acquire();
boolean wasAdded = false;
try {
wasAdded = set.add(o);
return wasAdded;
} finally {
//返回许可给信号量
if (!wasAdded)
sem.release();
}
}
public boolean remove(Object o) {
boolean wasRemoved = set.remove(o);
if (wasRemoved)
sem.release();
return wasRemoved;
}