【发布时间】:2012-12-19 19:24:55
【问题描述】:
有没有办法知道信号量对象在其生命周期中拥有的最大许可数是多少? 我们像这样初始化它:
Semaphore sem = new Semaphore(n);
有时我们获得,有时我们释放我们获得的东西。但是在某些情况下,我们需要释放比我们获得的更多的数量来增加许可证的数量。有没有办法知道此信号量中的最大许可数?
【问题讨论】:
-
不要认为使用标准信号量是可能的。你想达到什么目的?
有没有办法知道信号量对象在其生命周期中拥有的最大许可数是多少? 我们像这样初始化它:
Semaphore sem = new Semaphore(n);
有时我们获得,有时我们释放我们获得的东西。但是在某些情况下,我们需要释放比我们获得的更多的数量来增加许可证的数量。有没有办法知道此信号量中的最大许可数?
【问题讨论】:
构造函数定义为public Semaphore(int permits)。 int 的最大值是 231 -1 = 2147483647 所以这就是你的答案。
【讨论】:
int 始终是一个 32 位有符号数。 long 始终是一个 64 位有符号整数。即使在 64 位 JVM 上,引用通常也是 32 位的。
信号量本身不会在其生命周期内跟踪最大值。围绕它实现一个跟踪最大值的 Semphore 包装器可能会很棘手。以下是此类实现的速写:
public final class MySemaphore {
private final Semaphore semaphore;
private final AtomicReference<MaxCounter> maxCounter = new AtomicReference<>();
public MySemaphore(int initialAvailable) {
this.semaphore = new Semaphore(initialAvailable);
maxCounter.set(new MaxCounter(initialAvailable, initialAvailable));
}
private static final class MaxCounter {
private final int value;
private final int max;
public MaxCounter(int value, int max) {
this.value = value;
this.max = max;
}
public MaxCounter increment() {
return new MaxCounter(value + 1, Math.max(value + 1, max));
}
public MaxCounter decrement() {
return new MaxCounter(value - 1, max);
}
public int getValue() {
return value;
}
public int getMax() {
return max;
}
}
public void acquire() throws InterruptedException {
semaphore.acquire();
for (;;) {
MaxCounter current = maxCounter.get();
if (maxCounter.compareAndSet(current, current.decrement())) {
return;
}
}
}
public void release() {
for (;;) {
MaxCounter current = maxCounter.get();
if (maxCounter.compareAndSet(current, current.increment())) {
break;
}
}
semaphore.release();
}
public int availablePermits() {
return maxCounter.get().getValue();
}
public int getMaximumEverAvailable() {
return maxCounter.get().getMax();
}
}
MaxCounter 可能与内部使用的信号量不完全同步。内部信号量可能会获得释放/获取,从外部角度来看,该释放/获取被处理为获取/释放。对于 MySemaphore 的每个客户端,尽管行为是一致的。即availablePermits() 永远不会返回高于getMaximumEverAvailable() 的值
免责声明:代码未经测试*
【讨论】: