How to release all permits for a Java Semaphore

java, multithreading, semaphore

Solution

As explained in other answers, there is a solution to make your piece of code atomic. However, there is no guarantee that it will solve the problem, in a general setting, simply because this code cannot be correct in all situations.

Either permits are released by activities using them, in which case that code is superfluous: the semaphore will be replenished naturally, or they don't, in which case you will need that piece of code, and it will be safe, as long as you don't do anything weird with it.

Note that you state that you wish to limit the rate of activities per time quantum (here a minute), but you must take in account that activities may last longer than an minute. There are really two different things that you can limit here:

- the number of activities starting per quantum,

- the number of activities running in a quantum

If you wish to limit the first, then you will need your code to refill the permits, and let activites keep their permits. If you want to handle the second case, then you must force activities to acquire and release their permit when starting and terminating respectively.

If you are afraid about a misuse of the semaphore by some activities, just forbid its use in the activity code itself. Indeed, the rate limiting is completely orthogonal to the activity semantics, and it's better to separate that functionality from the activity main code. Therefore you should wrap any scheduled activity with the code to handle the semaphore:

class RateLimitedRunnable implements Runnable {
    Runnable runnable;
    RateLimitedRunnable(Runnable r) { runnable = r; }
    void Run() {
        semaphore.acquire();
        runnable.run();
        semaphore.release(); // remove if only limiting starts
    }
}

The sample (untested) code above describe a possible handling of the use of semaphore away from the real activity, thus removing any potential misuse. If the inner activity needs to access the semaphore, it should only be to retrieve its current state, and an ad-hoc interface can surely be designed to provide that limited access.

Note: I use the "activity" term here as a mean for threads or processes, since the discussion on uses of semaphores is more general than the context of Java.

Problem

So this code: ``` int usedPermits = totalPermits - semaphore.availablePermits(); semaphore.release(usedPermits); ``` Isn't threadsafe, because if between the two lines another thread releases a permit, semaphore's capacity will actually increase above its original maximum. This works in my situation since this strip of code is 1) single-threaded and 2) the only place from which permits are released, which may simply illustrate the fact that "release all" and "acquire/release" are two incompatible design patterns on the same object. However, I want to ask if there is preferred pattern with a less subtle thread synchronization policy.

Original source