0

Is there a way of knowing what is the MAXIMUM number of permits that a semaphore object has ever had in its' lifetime? We initialize it like this:

Semaphore sem = new Semaphore(n);

and at times we acquire, and at times we release what we acquired. But there are certain situations when we need to release more than we acquired in order to increase the number of permits. Is there a way to know the MAXIMUM number of permits that ever was in this semaphore?

TheNotMe
  • 1,048
  • 2
  • 17
  • 33

2 Answers2

2

The constructor is defined as public Semaphore(int permits). The maximum of int is 231 -1 = 2147483647 so this is your answer.

rekire
  • 47,260
  • 30
  • 167
  • 264
  • For a 32-bit architecture. – czchlong Dec 19 '12 at 19:29
  • 2
    So far I know is a int every time defined as a 4 byte value. But I'll check this now. – rekire Dec 19 '12 at 19:31
  • Haha no that was not my question. My question is the maximum that I have EVER inputted into this specific semaphore. – TheNotMe Dec 19 '12 at 19:31
  • 2
    @TheNotMe Keep another variable that tracks it individually? – czchlong Dec 19 '12 at 19:33
  • @czchlong [int is everytime 4bytes](http://stackoverflow.com/q/400477/995926). I never used a value bigger than 3. I cannot imagine that there is a useful case to use a bigger value. – rekire Dec 19 '12 at 19:34
  • 2
    In Java an `int` is always a 32-bit signed number. and a `long` is always a 64-bit signed integer. A reference is usually 32-bit even on 64-bit JVMs. – Peter Lawrey Dec 19 '12 at 19:57
2

Semaphore itself does not keep track of a maximum over its lifetime. Implementing a Semphore wrapper around it that keeps track of the maximum can be tricky. Here's a quick draft of such an implementation :

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();
    }
}

The MaxCounter may not be exactly in sync with the internally used semaphore . The internal semaphore may get a release/acquire which is handled from an external perspective as acquire/release. To every client of MySemaphore, though the behavior will be consistent. i.e. availablePermits() will never return a value that is higher than getMaximumEverAvailable()

disclaimer : code not tested*

bowmore
  • 10,842
  • 1
  • 35
  • 43