【问题标题】:Java Semaphore maximum?Java信号量最大?
【发布时间】:2012-12-19 19:24:55
【问题描述】:

有没有办法知道信号量对象在其生命周期中拥有的最大许可数是多少? 我们像这样初始化它:

Semaphore sem = new Semaphore(n);

有时我们获得,有时我们释放我们获得的东西。但是在某些情况下,我们需要释放比我们获得的更多的数量来增加许可证的数量。有没有办法知道此信号量中的最大许可数?

【问题讨论】:

  • 不要认为使用标准信号量是可能的。你想达到什么目的?

标签: java semaphore


【解决方案1】:

构造函数定义为public Semaphore(int permits)。 int 的最大值是 231 -1 = 2147483647 所以这就是你的答案。

【讨论】:

  • 对于 32 位架构。
  • 到目前为止,我知道每次定义为一个 4 字节值的 int。但我现在会检查一下。
  • 哈哈不,这不是我的问题。我的问题是我输入到这个特定信号量的最大值。
  • @TheNotMe 保留另一个单独跟踪它的变量?
  • 在 Java 中,int 始终是一个 32 位有符号数。 long 始终是一个 64 位有符号整数。即使在 64 位 JVM 上,引用通常也是 32 位的。
【解决方案2】:

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

免责声明:代码未经测试*

【讨论】:

  • 使用 AtomicLong 结合 CAS 操作之一可能会更简单。
猜你喜欢
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-07
  • 2013-03-18
相关资源
最近更新 更多