Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't understand the need for Monitor.Pulse()

According to MSDN, Monitor.Wait():

Releases the lock on an object and blocks the current thread until it reacquires the lock.

However, everything I have read about Wait() and Pulse() seems to indicate that simply releasing the lock on another thread is not enough. I need to call Pulse() first to wake up the waiting thread.

My question is why? Threads waiting for the lock on a Monitor.Enter() just get it when it's released. There is no need to "wake them up". It seems to defeat the usefulness of Wait().

eg.

static object _lock = new Object();

static void Main()
{
    new Thread(Count).Start();
    Sleep(10);

    lock (_lock)
    {
         Console.WriteLine("Main thread grabbed lock");
         Monitor.Pulse(_lock) //Why is this required when we're about to release the lock anyway?
    }
}

static void Count()
{
    lock (_lock)
    { 
        int count = 0;

        while(true)
        {
            Writeline("Count: " + count++);

            //give other threads a chance every 10th iteration
            if (count % 10 == 0)
                 Monitor.Wait(_lock);
        }
    }
}

If I use Exit() and Enter() instead of Wait() I can do:

static object _lock = new Object();

static void Main()
{
    new Thread(Count).Start();
    Sleep(10);

    lock (_lock) Console.WriteLine("Main thread grabbed lock");
}

static void Count()
{
    lock (_lock)
    { 
        int count = 0;

        while(true)
        {
            Writeline("Count: " + count++);

            //give other threads a chance every 10th iteration
            if (count % 10 == 0)
            {
                 Monitor.Exit(_lock);
                 Monitor.Enter(_lock);
            }
        }
    }
}
like image 605
GazTheDestroyer Avatar asked Aug 31 '25 16:08

GazTheDestroyer


2 Answers

You use Enter / Exit to acquire exclusive access to a lock.

You use Wait / Pulse to allow co-operative notification: I want to wait for something to occur, so I enter the lock and call Wait; the notifying code will enter the lock and call Pulse.

The two schemes are related, but they're not trying to accomplish the same thing.

Consider how you'd implement a producer/consumer queue where the consumer can say "Wake me up when you've got an item for me to consume" without something like this.

like image 141
Jon Skeet Avatar answered Sep 02 '25 05:09

Jon Skeet


I myself had this same doubt, and despite some interesting answers (some of them present here), I still kept searching for a more convincing answer.

I think an interesting and simple thought on this matter would be: I can call Monitor.Wait(lockObj) at a particular moment in which no other thread is waiting to acquire a lock on the lockObj object. I just want to wait for something to happen (some object's state to change, for instance), which is something I know that will happen eventually, on some other thread. As soon as this condition is achieved, I want to be able to reacquire the lock as soon as the other thread releases its lock.

By the definition of the Monitor.Wait method, it releases the lock and tries to acquire it again. If it didn't wait for the Monitor.Pulse method to be called before trying to acquire the lock again, it would simply release the lock and immediately acquire it again (depending on your code, possibly in loop).

That is, I think it's interesting trying to understand the need of the Monitor.Pulse method by looking at its usefulness in the functioning of the Monitor.Wait method.

Think like this: "I don't want to release this lock and immediately try to acquire it again, because I DON'T WANT to be ME the next thread to acquire this lock. And I also don't want to stay in a loop containing a call to Thread.Sleep checking some flag or something in order to know when the condition I'm waiting for has been achieved so that I can try to reacquire the lock. I just want to 'hibernate' and be awaken automatically, as soon as someone tells me the condition I'm waiting for has been achieved.".

like image 31
Marcos Arruda Avatar answered Sep 02 '25 06:09

Marcos Arruda