Is it better to synchronize with semaphores or with monitors?
-
what's your specific problem that requires synchronization? – irreputable Feb 22 '11 at 21:08
-
13generally either is better than the other, at the same time also worse. – irreputable Feb 22 '11 at 21:14
4 Answers
"Better" depends on context. They are "equally powerful" according to James McParlane. I highly recommend viewing his blog for a discussion on the differences.
Here is a quick guide I found:
Semaphores
- Can be used anywhere in a program, but should not be used in a monitor
Wait()
does not always block the caller (i.e., when the semaphore counter is greater than zero).Signal()
either releases a blocked thread, if there is one, or increases the semaphore counter.- If
Signal()
releases a blocked thread, the caller and the released thread both continue.
Condition Variables
- Can only be used in monitors
Wait()
always blocks the caller.Signal()
either releases a blocked thread, if there is one, or the signal is lost as if it never happens.- If
Signal()
releases a blocked thread, the caller yields the monitor (Hoare type) or continues (Mesa Type). Only one of the caller or the released thread can continue, but not both.
This information from: http://www.cs.mtu.edu/~shene/NSF-3/e-Book/MONITOR/sema-vs-monitor.html
Some useful resources:
-
3This is interesting in general but is not directly applicable to Java, and hence slightly confusing. Hoare and Mesa monitors wha? – Air May 08 '12 at 15:55
-
Yes, the question was asked for Java, but the answer is not related to Java. – t0r0X Nov 21 '12 at 18:10
If you are after headache minimization, prefer the monitors (synchronized
blocks/methods) over semaphores wherever you feel a real choice of a locking primitive.
Ignore academical talk about flexibility of semaphores. You are after reliability, not configurability, aren't you?
It is often claimed that monitors and semaphores are equivalent (can simulate each other), but this equivalence is far more abstract and less helpful than is sometimes expected. Anyone who can correctly simulate one with the other does not need any answer to this question anymore.
Obviously, semaphores are your only practical choice in situations where the number of threads to be allowed to simultaneously enter a block is larger than one. So the real competitor of monitors are binary semaphores, namely those that are initialized with a count of 1, and additionally only those of them where you expect the same thread that did the locking to eventually unlock the semaphore. So let's look closer at exactly those situations.
The fundamental difference between monitors and binary semaphores is thread ownership. It has a big consequence, and that is the capability of reentrancy. Reentrancy means that a thread that already owns a lock can acquire it again as opposed to deadlocking. This is a big deal if your class has shared state that you simply want to protect in all methods but cannot afford permanent assumptions about how these methods call each other; or with any belt and braces traits that evolve in your thread safety scheme in general.
Semaphores are never reentrant and Java monitors are always reentrant. If you need to lock the same object from many code locations, semaphores are prone to deadlocks even in single threaded scenarios - and this limitation of semaphores brings any benefits only in relatively rare scenarios where monitors are not really an option anyway.
Thread ownership also drammatically reduces the risk of forgetting to lock, forgetting to unlock, or one thread's activities masking activities of another thread. There is also a significant ergonomic difference in the associated Java syntax.
Notice also this question; although it uses a different terminology, the better answers there understand "mutex" to mean a Java "monitor".

- 1
- 1

- 13,301
- 3
- 46
- 75
To confirm, by monitors we mean the good old synchronized
keyword.
First question, do you need your lock to have a counter?
- A Semaphore can have a counter greater than one. If you need to protect N resources, the Semaphore is best. Easy decision.
- If you're protecting a single resource, this is the interesting case where a Semaphore(1) and monitor are equally applicable.
The J2SE 5.0 concurrency article gives great advice here. Monitors are limited because :
- No way to back off from an attempt to acquire a lock that is already held, or to give up after waiting for a specified period of time, or to cancel a lock attempt after an interrupt.
- No way to alter the semantics of a lock, for example, with respect to reentrancy, read versus write protection, or fairness.
- Synchronization is done within methods and blocks, thus limiting use to strict block-structured locking. In other words, you cannot acquire a lock in one method and release it in another.
So if any of these items is important to you - backing off after a timeout is a great example - then go with a Semaphore. If not, a monitor is fine.

- 5,084
- 5
- 25
- 19
First of all, you have to decide which JDK are you using. The first Java releases where only provided of Threads. Since the Java Tiger (5.0), new classes have been introduced to handle concurrency. In particular, a complete package has been provided, the java.util.concurrent.
In my experience, I found that monitors are better, since they let the code more clean. Moreover, using them let the code more easy-to-understand. They are generally implemented through a class that implements the Lock interface: the most famous implementations provided by the JDK are the ReentrantLock class, which defines a general lock, and the ReentrantReadWriteLock class, that provides a specific write and/or read lock.
Threfore, a lock is used to enable/disable the access to a shared object (e.g. a list of objects).
A Semaphore object is a synchronized used to coordinate and control the threads (there are many synchronizers provided in the latest JDKs, like Semaphore, CyclicBarrier, CountdownLatch, and Exchanger classes). For instance, with a Semaphore you can release a fixed number of tokens to your pool of Threads and so decide the amount of operations that can be executed simultaneously. Personally, I don't like this approach, since the use of a pool of thread with Futures and Locks lead to the same result in a cleaner and safer way.
More info can be found in this book: "Java Concurrency in Practice" and in this IBM's tutorial: "Concurrency in JDK 5.0". Some more nice examples can be found here.

- 17,172
- 23
- 113
- 157