I am reading about Condition in java.util.concurrent.locks.Condition
.
Condition factors out the Object monitor methods (wait, notify and notifyAll) >into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations.
Can somebody explain me this?
How this is a benefit over normal synchronization blocks or method?
For a bounded DataStructure for example, you can have the Conditions "notEmpty" and "notFull" and wait for them. Just one example. Have a look at the example here.
Previously before the Explicit Locks we used Object
wait()
andnotify()
methods for making threads to wait until some event occurred and then triggering them usingnotify()
and the mutex of that Object must be with the thread calling these methods.So there was only one wait-set per lock object. Wait set is the set where the threads that call
wait()
on the object are stored (not literraly).But with the Explicit Lock framework using a single lock you can create multiple wait-sets for different conditions that are related to the same lock. As the example in Javadoc also explain the same fact.
So as in the case of Buffer example from JavaDoc consumer threads will wait on the condition for the Buffer to be NOT EMPTY and the producer threads will wait on the condition NOT FULL.
One Lock can be associated with many Conditions. Lock is an "object", each condition is a "waiting set". This allows for independent conditions sharing critical section. For example, consider bounded producers-consumers problem. One way to solve it is to have one lock that protects the queue, and two independent waiting sets: one for producers, waiting for slot to place item in the queue, other for consumers waiting for items to take. Using plain old
synchronized
andwait/notify
API, best we can do is along these lines:producer:
consumer:
This has the disadvantage of waking up both producers and consumers on every change to the queue, even if it cannot possibly allow given thread to proceed (e.g. consumer is awoken when some other consumer takes item from the queue). Using Lock/Condition API we can implement solution that separates waiting consumers and producers, and hence reduce redundant wakeups and checking:
producer:
consumer:
This way, consumer waits for producers to produce some item (hasItems condition), and upon removing an item from the queue it notifies producers that there is an empty slot (hasPlace condition). Both conditions are associated with the same critical section (Lock), so we keep the usual exclusion and release-lock-while-waiting guarantees, while gaining the ability to separate waiting queues.