Java Concurrency Interview

Synchronizers: latches, barriers, semaphores question 52 of 180 mid

Why must a Semaphore release live in a finally, and what goes wrong if it does not?

Permits are a plain count, not an ownership record. Nobody tracks that your thread holds one, so nothing returns it if you throw, return early or get interrupted between acquire and release. A Semaphore(50) in a code path that fails one call in a thousand becomes a Semaphore(0) after enough traffic, and the symptom is a service that goes quiet over days with no error to point at.

semaphore.acquire();
try {
    call();
} finally {
    semaphore.release();      // the only correct place
}

The mirror image is releasing without acquiring, in a retry path or a stray cleanup, which raises the ceiling above the real limit and overloads the thing you were protecting. Both are silent. Exporting availablePermits() as a metric is the cheapest way to see either one coming.

synchronizers semaphore antipattern

Quiz yourself on Synchronizers: latches, barriers, semaphores Suggest a correction