Java信号量最大?

2022-05-11 00:00:00 semaphore java
有没有办法知道信号量对象在其生命周期中曾经拥有的最大许可数量? 我们按如下方式进行初始化:

Semaphore sem = new Semaphore(n);

有时我们获得,有时我们释放我们所获得的。但在某些情况下,我们需要发放比我们获得的更多的许可证,以增加许可证的数量。有没有办法知道此信号量中曾经出现过的最大许可数?


解决方案

信号量本身不跟踪其生存期内的最大值。在它周围实现一个跟踪最大值的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()的值

免责声明:代码未测试*

相关文章