29

Please tell what is difference between a Semaphore initialized with 1 and Vs. intialized zero, as below:

public static Semaphore semOne = new Semaphore(1);

and

public static Semaphore semZero = new Semaphore(0);
Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
Atul Kumar
  • 719
  • 3
  • 8
  • 29
  • It specifies the *permits*. check [here](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html) – TheLostMind Aug 29 '14 at 07:37
  • @TheLostMind javadocs mention a negative permits, but not zero – Scary Wombat Aug 29 '14 at 07:38
  • 1
    It behaves same as in the case if the permits is negative. We need to call release() on semaphore before calling acquire(). – Manjunath Aug 29 '14 at 07:46
  • how many threads will be able to acquire once the semzero is released? is it 1? basically what's no of permits allowed by semzero –  Feb 11 '18 at 04:32
  • Is it then possible to keep calling release() on the Semaphore (SemZero) and make it be able to behave like having more permits? – java_geek May 10 '20 at 03:39

3 Answers3

35

The argument to the Semaphore instance is the number of "permits" that are available. It can be any integer, not just 0 or 1.

For semZero all acquire() calls will block and tryAcquire() calls will return false, until you do a release()

For semOne the first acquire() calls will succeed and the rest will block until the first one releases.

The class is well documented here.

Parameters: permits - the initial number of permits available. This value may be negative, in which case releases must occur before any acquires will be granted.

Achala Dissanayake
  • 810
  • 3
  • 16
  • 33
Chip
  • 3,226
  • 23
  • 31
  • how many threads will be able to acquire once the semzero is released? is it 1? basically what's no of permits allowed by semzero –  Feb 11 '18 at 04:31
  • 3
    @ETHER none. If it's 0 then you need to release it 1st before anyone can acquire it. – Aniket Thakur Jan 19 '19 at 07:33
  • Is it possible to keep calling release() on the Semaphore (SemZero) multiple times before an acquire can be invoked? – java_geek May 10 '20 at 03:41
9

the constructor parameter permits (initial semaphore counter) is the number of calls to Semaphore.aquire() that can be made before the counter (permits) is zero, and the acquire()blocks.

1 is a normal value, to ensure that only one thread passes the acquire.

semaphore.acquire();
try {
    // Critical region
    ...
} finally {
    semaphore.release();
}

For a usage of 0 see here.

Semaphore is a low-level mechanism for concurrency: a counter when reaching zero blocking thread execution. It stems from Dijkstra where the binary semaphore (0, 1) is a metaphore for a railway semaphore saying pass (halt when 0, pass --permits) and at the end of the protected track does a release (++permits).

Community
  • 1
  • 1
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • how many threads will be able to acquire once the semzero is released? is it 1? basically what's no of permits allowed by semzero –  Feb 11 '18 at 04:32
  • @developer Consider `... acquire(); [Critical Section] release(); ...` will allow exactly one other `acquire()` (called after the first acquire) to pass. In Computer Science the Dutch Dijkstra used the train analogy: semaphore, P=passeren=try-pass/acquire, V=vrij maken=release. – Joop Eggen Feb 11 '18 at 21:08
7

When I first read the documentation of the Semaphore I also misinterpreted the explanation. The main point I missed was the part of '...INITIAL number of permits...'. Somehow I though this would be the number of permits which would be available as a MAXIMUM, but that is NOT the case. In the end the semaphore just counts up from any number but only starts the enable waiting threads (which use the acquire) when the semaphore permits are above 1.

A simple piece of (non threading) code shows this too:

@Test
public void testNegativeSemaphore()
{
    Semaphore semaphore = new Semaphore(-2);

    assertEquals(-2, semaphore.availablePermits());
    semaphore.release();
    assertEquals(-1, semaphore.availablePermits());
    semaphore.release();
    assertEquals(0, semaphore.availablePermits());
    semaphore.release();
    assertEquals(1, semaphore.availablePermits());
}

As the code shows, the available permits increase upon each release, only to allow other threads to acquire a permit once the value reaches 1 or above.

NOTE that from there on the availablePermits cannot become negative by using the aqcuire because if there are 0 permits the whole point of the semaphore is to wait for a permit to become available again!

Morten
  • 71
  • 1
  • 2