Monitor.Wait(object, timeout) confusion

F

Felix

I am a little new to windows synchronization, and I was very confused
for a bit by the documentation for Monitor.Wait.

It currently reads:

//Releases the lock on an object and blocks the current thread until
it reacquires //the lock or a specified amount of time elapses.
public static bool Wait(object, int);


If I understand it (and my vocabulary is probably a little off):

// releases the lock on the object and waits until it is singalled or
until the time specified elapses. It is then moved to the ready queue,
and blocks until it can reaquire the lock.
public static bool Wait(object, int timeout);


Furthermore, under the "remarks", I believe the text is just
completely wrong. For instance:

"Once the specified time has elapsed, this method returns a value that
indicates whether or not the lock has been reacquired by the caller."

This is not true, the method could very well block indefinately!!!

Comments appreciated.

Thanks,

Felix


Link to the comment [msdn]:
http://msdn.microsoft.com/library/d...frlrfsystemthreadingmonitorclasswaittopic.asp
 
J

Jon Skeet [C# MVP]

Felix said:
I am a little new to windows synchronization, and I was very confused
for a bit by the documentation for Monitor.Wait.

It currently reads:

//Releases the lock on an object and blocks the current thread until
it reacquires //the lock or a specified amount of time elapses.
public static bool Wait(object, int);


If I understand it (and my vocabulary is probably a little off):

// releases the lock on the object and waits until it is singalled or
until the time specified elapses. It is then moved to the ready queue,
and blocks until it can reaquire the lock.
public static bool Wait(object, int timeout);


Furthermore, under the "remarks", I believe the text is just
completely wrong. For instance:

"Once the specified time has elapsed, this method returns a value that
indicates whether or not the lock has been reacquired by the caller."

This is not true, the method could very well block indefinately!!!

Yes, I believe you're absolutely correct. I suggest you send your
feedback to the MSDN team using the link at the bottom of the page.
 
A

Axel Müller

Felix said:
I am a little new to windows synchronization, and I was very confused
for a bit by the documentation for Monitor.Wait.

It currently reads:

//Releases the lock on an object and blocks the current thread until
it reacquires //the lock or a specified amount of time elapses.
public static bool Wait(object, int);

Hello Felix,
the documentation is definitely NOT WRONG !
If I understand it (and my vocabulary is probably a little off):

// releases the lock on the object and waits until it is singalled or
until the time specified elapses. It is then moved to the ready queue,
and blocks until it can reaquire the lock.
public static bool Wait(object, int timeout);

Obviousley you did not unstand the whole sychronization process :
First you must Monitor.Enter the lock-object before you can
call Monitor.Wait .
If you call Monitor.Wait, the lock-object will be released and
another thread from the lock queue for the lock-object or
from a Monitor.Enter call will get the lock-object.

The Thread that called Monitor.Wait is placed at the end in a
dedicated queue associated with the lock, called 'wait queue'.
All the pending threads in the 'wait queue' are blocked.
If a timeout happened to the waiting thread it will be removed
from that wait queue and the Monitor.Wait method will return.

In the case that another thread ( owner of the lock object )
calls Monitor.Pulse :
The first waiting thread in the wait queue will removed from
this queue and will be added to the end of the lock queue,
REGARDLESS if it has an INFINITE timeout-Value or
not !!
If this thread in the lock queue later gets the lock object,
the Monitor.Wait will return ( regardless of an infinite
timeout-value for his Monitor.Wait-Method !)
Furthermore, under the "remarks", I believe the text is just
completely wrong. For instance:

NO ! IT IS COMPLETELY RIGHT !
"Once the specified time has elapsed, this method returns a value that
indicates whether or not the lock has been reacquired by the caller."

This is not true, the method could very well block indefinately!!!

NO, this is true !!!

Regards
Axel Mueller
 
J

Jon Skeet [C# MVP]

Axel Müller said:
the documentation is definitely NOT WRONG !

Well, while the detailed explanation is correct, the summary is very
misleading.
Obviousley you did not unstand the whole sychronization process :

Actually, I think he understands it pretty well...
First you must Monitor.Enter the lock-object before you can
call Monitor.Wait .
If you call Monitor.Wait, the lock-object will be released and
another thread from the lock queue for the lock-object or
from a Monitor.Enter call will get the lock-object.

So far we're agreed.
The Thread that called Monitor.Wait is placed at the end in a
dedicated queue associated with the lock, called 'wait queue'.
All the pending threads in the 'wait queue' are blocked.
If a timeout happened to the waiting thread it will be removed
from that wait queue and the Monitor.Wait method will return.

Not immediately it won't - it won't return until it has regained the
lock.
In the case that another thread ( owner of the lock object )
calls Monitor.Pulse :
The first waiting thread in the wait queue will removed from
this queue and will be added to the end of the lock queue,
REGARDLESS if it has an INFINITE timeout-Value or
not !!

And that's what the summary fails to mention. It doesn't talk about
pulsing at all - it just says that the method releases the lock and
blocks until the lock has been reacquired.
If this thread in the lock queue later gets the lock object,
the Monitor.Wait will return ( regardless of an infinite
timeout-value for his Monitor.Wait-Method !)

Sure.
NO ! IT IS COMPLETELY RIGHT !


NO, this is true !!!

Again, I disagree. The method has to block until it reacquires the
lock, whether or not it's been pulsed. The docs actually later say
this:

<quote>
However, if millisecondsTimeout elapses before another thread invokes
this object's Pulse or PulseAll method, the original thread is moved to
the ready queue in order to regain the lock.
</quote>

Putting the thread back to the ready queue is very different from
returning just a value to indicate whether or not the lock has been
reacquired. The lock will *always* have been reacquired (leaving aside
some interesting issues to do with Thread.Abort or Interrupt).

The first part of the documentation implies that if you call
Monitor.Wait (foo, 1000) the call will return after a second, pretty
much. As the OP wrote, it could actually block indefinitely, as
demonstrated below:

using System;
using System.Threading;

class Test
{
static object foo = new object();

static void Main()
{
new Thread (new ThreadStart(AcquireAndWait)).Start();
Thread.Sleep (200);

lock (foo)
{
while (true)
{
Console.WriteLine ("First thread sleeping");
Thread.Sleep (5000);
}
}
}

static void AcquireAndWait()
{
lock (foo)
{
Console.WriteLine ("Second thread waiting");
Monitor.Wait (foo, 1000);
Console.WriteLine ("Second thread finished waiting");
}
}
}

Please run the program above and tell us whether or not it blocks
indefinitely for you, contrary to the documentation which states:

<quote>
This method behaves identically to Wait(Object), except that it does
not block indefinitely unless Infinite is specified for the
millisecondsTimeout parameter.
</quote>
 
F

Felix

Thanks for the great discussion. Jon, I wrote a program almost
identical to the one you posted, and was suprised. I expected, after a
cursory reading of the msdn documention exactly what Axel describes:
Not immediately it won't - it won't return until it has regained the
lock.

Yes, exactly, it won't return until it has regained the lock. A fine
thing, but not what I first guessed :)

Felix
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top