To specifically indicate why having multiple waitsets is an advantage:
With waiting / notification, if there are different things that are waiting for threads (a common example is a lock of a fixed size, with some threads putting things in a queue and blocking when the queue is full, and other threads taken from the queue and blocking when the queue is empty) , then if you use a notification, forcing the scheduler to select one thread from the waiting set for notification, you may have angular cases when the selected thread is not interested in receiving notification of a specific situation. For example, the queue will notify when something is added to the queue, but if the selected stream is a producer and the queue is full, then it cannot act on this notification, which you prefer to use for the consumer. With internal locking, you should use notifyAll to make sure that notifications are not lost.
But notifyAll crashes on every call, where each thread wakes up and protects the lock, but only one can make progress. The rest of the threads all collide, fighting for a lock, until, one at a time, they can get a lock and, most likely, return to waiting. It generates a lot of disagreement, which does not bring much benefit, it would be preferable to be able to use the notification and know that only one stream is notified, where the notification refers to this stream.
There are separate waiting conditions - this is a big improvement. A queue can cause a signal under the condition and know that it will awaken only one thread, where this thread specifically expects a condition.
The doc for Condition API has sample code that shows the use of several conditions for a limited buffer, it says:
We would like to continue waiting to set streams and receive streams in separate waiting sets, so that we can use optimization only to notify one stream at a time when elements or spaces become available in the buffer.
Nathan Hughes Apr 21 '17 at 15:27 2017-04-21 15:27
source share