35
votes

I've been trying to understand Reentrant locks and Semaphores ( the nesting of Reentrant locks vs release/unlock mechanism ).

It seems that having a Semaphore requires you to write a more thoroughly tested application because the release() method does not check if the thread releasing the permit is actually holding it. When I tested my test code, I found out that this may subsequently increase the number of permits beyond the initial limit. On the other hand, if a thread is not holding a reentrant lock when it invokes the unlock method, we get an IllegalMonitorException.

So would it be right to say that there is no real reason ever to have a binary semaphore as everything that a binary semaphore can do can also be done by a ReentrantLock. If we use binary semaphores we would have to check the entire method call stack to see if a permit was acquired before ( also was it released too if there is a possibility of a subsequent acquire - which might block if a release does not proceed it and so on ). Also since reentrant locks also provide one lock per object, isn't it always a better idea to prefer a reentrant lock to a binary semaphore?

I have checked a post here that talks about difference between a binary semaphore and a mutex but is there a thing like a mutex in Java?

Thanks, Chan.

P.S - I had posted this question in another forum ( http://www.coderanch.com/t/615796/threads/java/reason-prefer-binary-Semaphore-Reentrant ) and I haven't received a response yet. I thought I'd post it here as well to see what I can get.

3
stackoverflow.com/questions/12641933/… may helpuser2579943
That behaviour is by design and well documented: "There is no requirement that a thread that releases a permit must have acquired that permit by calling acquire(). Correct usage of a semaphore is established by programming convention in the application.". When using ReentrantLocks, you must ensure you properly release your lock in a finally block. That is not enforced either but is well documented too.assylias

3 Answers

35
votes

there is no real reason ever to have a binary semaphore as everything that a binary semaphore can do can also be done by a ReentrantLock

If all you need is reentrant mutual exclusion, then yes, there is no reason to use a binary semaphore over a ReentrantLock. If for any reason you need non-ownership-release semantics then obviously semaphore is your only choice.

Also since reentrant locks also provide one lock per object, isn't it always a better idea to prefer a reentrant lock to a binary semaphore?

It depends on the need. Like previously explained, if you need a simple mutex, then don't choose a semaphore. If more than one thread (but a limited number) can enter a critical section you can do this through either thread-confinement or a semaphore.

I have checked a post here that talks about difference between a binary semaphore and a mutex but is there a thing like a mutex in Java?

ReentrantLock and synchronized are examples of mutexes in Java.

8
votes

I will not explain re-entrant locks since John has already given a good explanation above and its an example of mutex in java along with Synchronized keyword.

However, if for any reason, you would like to have a better control over the locking mechanism, Semaphore can become handy. This means, your code will have to remain in-charge of who called acquire() and who called release() since Semaphore by nature is blind to it, all it cares is permit becomes available.

Another approach of your own mutex implementation using java is LockSupport. It works a bit like Semaphore but has a timeout on the permit, using park() function and only supports one permit at a time unlike Semaphores which support multiple of them.

3
votes

There are some small differences between Semaphore and reenterant lock.

  • Semaphore may be released by another thread. Semaphore's javadoc states that such behavior may be useful in some specialized contexts like deadlock recovery. So it should be a really specialized contexts.
  • Also binary semaphores are not reenterant. You cannot acquire a binary semaphore second time in a same thread. It will lead to a deadlock (deadlocking thread with itself!) and you may need some means of already mentioned deadlock recovery