Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting queue vs. Ready queue

Tags:

.net

Why is there a Ready and Waiting queue for every object when using a monitor? If a thread is done with an object, just pop the next item in the Waiting queue. The Ready queue seems redundant.

The context is .NET, more specifically the monitor class.

like image 256
Yamcha Avatar asked Nov 22 '25 15:11

Yamcha


2 Answers

A producer/consumer queue is a really good use case for learning about the Monitor class.

Assume that work is sporadically added to the queue. Sometimes there are a lot of items needing to be processed, sometimes long periods of time will elapse with no items in the queue.

So, let's say you have k consumer threads waiting around to process items in the queue. In other words, each thread implements a tight loop, constantly trying to

  1. Request to get the lock on the queue (this puts you in the Monitor's "ready" queue).
  2. Once you get the lock, check if the queue has any items. If not, you have two choices for releasing the lock: a) Call Monitor.Exit, and then call Monitor.Enter to put yourself in the back of the "ready" queue. b) Or, call Monitor.Wait, and put yourself in the Monitor's "waiting" queue.

If you choose option "a", your k threads will be wasting CPU cycles moving through the ready queue over and over, finding no work to do, and starting all over again at the back of the queue.

If you choose option "b", you're saying "there's nothing here to do right now, let me sleep, and wake me up when there's something to do".

With option "b", if the queue is empty, you will soon find all of your consumers sleeping in the "waiting" queue, and no CPU time being wasted.

Then, when a producer adds an item to the queue, it calls Monitor.Pulse. This wakes up the first thread in the "waiting" queue, which then goes to the back of the "ready" queue (which is also the front of the queue if the "ready" queue was empty).

When a thread gets the lock and consumes this item from the queue, it calls Monitor.Enter again, and goes to the back of the "ready" queue.

See this article for a classic implementation of a producer/consumer queue in .NET.

like image 58
mbeckish Avatar answered Nov 24 '25 05:11

mbeckish


Assuming I've understood your question properly, the two serve different purposes.

The "ready" queue is for threads which are ready to run as soon as they can obtain the lock. They're just waiting to acquire the lock. This is mostly used for mutual exclusion, to prevent two threads from both using the same resource at the same time.

The "waiting" queue is for threads which are waiting for a particular signal - namely the monitor being pulsed. This is often used for co-ordination - for example in a producer/consumer queue, where if the queue is empty, a consumer will wait until a monitor is pulsed before it checks the queue again. While no-one is producing and no-one is consuming, no thread owns the monitor - there's no resource in use. But the monitor is used to co-ordinate the consumer with the producer.

like image 44
Jon Skeet Avatar answered Nov 24 '25 07:11

Jon Skeet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!