From: Tony Johansson on
Hi!

Here I have a program that works but I don't really understand how it works
as it does.
This program is using two threads. It's the main thread and a secondary
thread.
When the secondary thread is executing this statement
Monitor.Wait(locker);
in method ConsumeMessage it will release the locker lock and wait until the
main thread is calling the Monitor:Pulse.
Now when the main thread is executing this statement
Monitor.Pulse(locker);
it will send a signal to the secondary thread that you have some work to do
now.
the secondary thread will start and grab the locker object but how can it do
so without calling this row
lock (locker) in the method ConsumeMessage.
I have tested this by adding this row
Console.WriteLine("Just before the while loop");
just before the while loop in method ConsumeMessage
and this row is not being executed.

I know the secondary thread will grab the locker object in some way without
calling this row
lock (locker).

So my question is just how is that possible ?

class Program
{
private static bool messageExists = false;
private static readonly object locker = new object();
private static String message = null;

static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(ConsumeMessage));
t.Name = "Consumer thread";
t.Start();
Thread.Sleep(2000);
lock (locker)
{
Console.WriteLine("Producer thread: message produced.");
message = "New message: hi!";
messageExists = true;
Console.WriteLine("Producer thread: about to pulse waiting
threads...");
Monitor.PulseAll(locker);
Thread.Sleep(5000);
}
t.Join();
Console.WriteLine("Press any...");
Console.ReadKey();
}

private static void ConsumeMessage()
{
lock (locker)
{
Console.WriteLine("Just before the while loop");
while (!messageExists)
{
Console.WriteLine(Thread.CurrentThread.Name + " : No
message....hibernating...");
Monitor.Wait(locker);
}
Console.WriteLine(Thread.CurrentThread.Name+"--> Message
consumed: "+message);
}
}
}

//Tony


From: Peter Duniho on
Tony Johansson wrote:
> Hi!
>
> Here I have a program that works but I don't really understand how it works
> as it does.
> This program is using two threads. It's the main thread and a secondary
> thread.
> When the secondary thread is executing this statement
> Monitor.Wait(locker);
> in method ConsumeMessage it will release the locker lock and wait until the
> main thread is calling the Monitor:Pulse.
> Now when the main thread is executing this statement
> Monitor.Pulse(locker);
> it will send a signal to the secondary thread that you have some work to do
> now.
> the secondary thread will start and grab the locker object but how can it do
> so without calling this row
> lock (locker) in the method ConsumeMessage. [...]

The documentation is quite clear on the question. The Monitor.Wait()
method does not return until it has successfully re-acquired the lock.
This will not happen until the other thread that called Monitor.Pulse()
has released it (e.g. by leaving the "lock (locker) { � }" protected
block of code).

Pete