How and why can a Semaphore give out more permits than it was initialized with?

11,904

Solution 1

Instead of "handing out" permit objects, the implementation just has a counter. When a new permit is "created" the counter is increased, when a permit is "returned" the counter is decreased.

This makes for much better performance than creating actual objects all the time.

The tradeoff is that the Semaphore itself cannot detect certain kinds of programming errors (such as unauthorized permit cash-ins, or semaphore leaks). As the coder, you have to make sure to follow the rules on your own.

Solution 2

I think that it means the times what we may require Semaphore as the times we released "extra" and plus the permits it created with.

Such as:

Semaphore s = new Semaphore(1); // one permit when initialize

s.acquire();
s.release();

s.release(); // "extra" release.

At this moment, this semaphore allows one permit originally and one "extra" permit

Solution 3

Can somebody explain this ? From the above statement, it looks like the "permits" can keep growing.

A semaphore is a counter of permits. acquire is like decrement which waits rather than go below zero. It has no upper limit.

Why is it designed this way ?

Because its simple to do so.

Solution 4

As mentioned in first post "Semaphore is not limited to the number of permits it was created with"

Every call to .release() API will increase the permit count by one. So Semaphores doesn't have a fixed permit size

Share:
11,904
Vinoth Kumar C M
Author by

Vinoth Kumar C M

buildit @ wiprodigital https://about.me/vinothkumar.cm

Updated on June 05, 2022

Comments

  • Vinoth Kumar C M
    Vinoth Kumar C M almost 2 years

    I am reading the book Java Concurrency in Practice. In a section about java.util.concurrent.Semaphore, the below lines are present in the book. It is a comment about its implementation of "virtual permit" objects

    The implementation has no actual permit objects, and Semaphore does not associate dispensed permits with threads, so a permit acquired in one thread can be released from another thread. You can think of acquire as consuming a permit and release as creating one; a Semaphore is not limited to the number of permits it was created with.

    Can somebody explain this? I am having trouble understanding this. If we create a pool of fixed size, we create a fixed number of "permits". From the above statement, it looks like the "permits" can keep growing. Why is it designed this way?

  • Scorpion
    Scorpion over 12 years
    No upper limit, wouldn't the upper limit be the number of permits?
  • Vishy
    Vishy over 12 years
    The upper limit is the number of times release minus the number of times acquire has been called. You can call release any number of times. There is an upper limit of Integer.MAX_VALUE in some implementations.
  • slott
    slott about 9 years
    So how does one go about creating a solid semaphore with a maximum of 1 - regardless of how many times release is called ?
  • Vishy
    Vishy about 9 years
    @slott for that I would use an AtomicBoolean. You can set(true) to release and compareAndSet(true, false) to acquire. This is non blocking.
  • slott
    slott about 9 years
    Is it overkill to extend Semaphore and override release to do a drainPermits() ?
  • Dasmowenator
    Dasmowenator about 8 years
    Does Java provide a different kind of semaphore which actually enforces the permit limit? I just want release() to be a no-op when all the permits have already been released... In a complex system with a lot of threads, it's not so easy to make sure that each thread always acquires and releases exactly one permit.
  • hansvb
    hansvb about 8 years
    @Dasmowenator: I suppose you could roll your own on top of AtomicInteger. But that does not sound like a good approach. You should really make sure your locking code is logically correct. If you find the need to make release a no-op, that probably means that someone was releasing more locks than they should have. And that will break things that cannot be fixed by just ignoring some semaphore calls.
  • hansvb
    hansvb about 8 years
    You could also use the traditional "synchronized" way of locking. Less flexible, but safe (no leaks, takes care of re-entrancy etc).
  • Neeraj Yadav
    Neeraj Yadav over 6 years
    can you explain the .release() working then? So, if i create a semaphore object with 0 then no thread can acquire permit from it? But if i call .release() on it first and then .acquire() in next line, it will allow a thread to acquire permit?
  • LookIntoEast
    LookIntoEast almost 3 years
    I'm confused by this for long; and looks crazy this is allowed