can anybody explain me with simple example to handle Monitor.PulseAll().I have already gone some examples from this stackoverflow.As i am a beginner i feel those are above my head.
How about (to show the interaction):
static void Main()
{
object obj = new object();
Console.WriteLine("Main thread wants the lock");
lock (obj)
{
Console.WriteLine("Main thread has the lock...");
ThreadPool.QueueUserWorkItem(ThreadMethod, obj);
Thread.Sleep(1000);
Console.WriteLine("Main thread about to wait...");
Monitor.Wait(obj); // this releases and re-acquires the lock
Console.WriteLine("Main thread woke up");
}
Console.WriteLine("Main thread has released the lock");
}
static void ThreadMethod(object obj)
{
Console.WriteLine("Pool thread wants the lock");
lock (obj)
{
Console.WriteLine("Pool thread has the lock");
Console.WriteLine("(press return)");
Console.ReadLine();
Monitor.PulseAll(obj); // this signals, but doesn't release the lock
Console.WriteLine("Pool thread has pulsed");
}
Console.WriteLine("Pool thread has released the lock");
}
Re signalling; when dealing with Monitor (aka lock), there are two types of blocking; there is the "ready queue", where threads are queued waiting to execute. On the line after Console.WriteLine("Pool thread wants the lock"); the pool queue enters the ready queue. When the lock is released a thread from the ready queue can acquire the lock.
The second queue is for threads that need waking; the call to Wait places the thread in this second queue (and releases the lock temporarily). The call to PulseAll moves all threads from this second queue into the ready queue (Pulse moves only one thread), so that when the pool thread releases the lock the main thread is allowed to pick up the lock again.
It sounds complex (and perhaps it is) - but it isn't as bad as it sounds... honestly. However, threading code is always tricky, and needs to be approached with both caution and a clear head.
Monitor.Wait() will always wait for a pulse.
So, the principal is:
When in doubt, Monitor.Pulse()
When still in doubt, Monitor.PulseAll()
Other than that, I'm not sure what you are asking. Could you please elaborate?
Edit:
Your general layout should be:
Monitor.Enter(lock);
try
{
while(!done)
{
while(!ready)
{
Monitor.Wait(lock);
}
// do something, and...
if(weChangedState)
{
Monitor.Pulse(lock);
}
}
}
finally
{
Monitor.Exit(lock);
}
Related
I have got this code :
if (Monitor.TryEnter(_lock))
{
try
{
ExecuteTask();
}
finally
{
Monitor.Exit(_lock);
}
}
else
{
Monitor.Enter(_lock);
Monitor.Exit(_lock);
}
Basically, if one thread is already executing the task the following threads should just wait for it to finish.
Is there a proper solution as opposed to the one I have found doing :
Monitor.Enter(_lock);
Monitor.Exit(_lock);
Thanks
If there is no need to block the others, you can just use this:
if (Monitor.TryEnter(_lock))
{
try
{
ExecuteTask();
}
finally
{
Monitor.Exit(_lock);
}
}
Personally, I would suggest a solution using Monitor.Wait and Monitor.PulseAll with an additional _executing flag like
Monitor.Enter(_lock);
if (_executing) { // Another thread is running ExecuteTask()
Monitor.Wait(_lock);
Monitor.Exit(_lock);
} else {
_executing = true;
Monitor.Exit(_lock);
try {
ExecuteTask();
} finally {
Monitor.Enter(_lock);
_executing = false;
Monitor.PulsaAll(_lock);
Monitor.Exit(_lock);
}
}
I think this is a bit cleaner: in your solution, holding the lock means "I'm currently updating" as well as "I just waited for another thread to complete the updating". This is not the "original" purpose of a lock (which is to manage exclusive access to some resource).
In my solution, the lock is used to manage exclusive access to the _executing flag.
Also note that the original code might have a subtle bug: I suppose that after one thread has finished ExecuteTask() the next thread arriving at the code should again perform this operation. No imagine this situation:
The first thread reaches the code and starts ExecuteTask()
The next thread reaches the code, TryEnter fails, the thread goes to the else branch and waits for Monitor.Enter() to succeed.
The first thread finishes ExecuteTask() and releases the lock
The second thread Enters the lock in the else branch.
and now:
While the second thread is between Enter and Exit, a third thread reaches the code. TryEnter fails (the second thread holds the lock), the third thread goes to the else branch.
Second thread calls Exit, Third Thread calls Enter, fourth thread arrives, tries Enter, goes to the else branch.
and so on...
So there is a scenario where no further thread ever calls ExecuteTask(), all following threads go straight into the else branch.
In your concrete situation this might be improbable or even impossible, but examples like these usually point to design flaws when it comes to parallel programming.
You can set the time each blocked thread waits using an argument to TryEnter
if (Monitor.TryEnter(_lock,TIMEOUT))//try to acquire lock for TIMEOUT miliseconds
{
try
{
//something
}
finally
{
Monitor.Exit(_lock);
}
}
else//lock was not acquired
{
//Handle TIMEOUT error
}
lock
{
Dispatcher.BeginInvoke(DispatcherPriority.Send, (SendOrPostCallback)delegate(object o)
{
DoSomething();
}
}
Does lock remains acquired Until Dispatcher completes its execution or released soon after sending the DoSomething(); for execution to Dispatcher?
Lock remains acquired until code under lock {} section completes its execution.
In your case that means: until Dispatcher.BeginInvoke completes its execution.
And as Dispatcher.BeginInvoke executes asynchronously, that means that lock gets released almost "immediately" - DoSomething() might start in the moment when lock has been already released.
Jeffrey Richter pointed out in his book 'CLR via C#' the example of a possible deadlock I don't understand (page 702, bordered paragraph).
The example is a thread that runs Task and call Wait() for this Task. If the Task is not started it should possible that the Wait() call is not blocking, instead it's running the not started Task. If a lock is entered before the Wait() call and the Task also try to enter this lock can result in a deadlock.
But the locks are entered in the same thread, should this end up in a deadlock scenario?
The following code produce the expected output.
class Program
{
static object lockObj = new object();
static void Main(string[] args)
{
Task.Run(() =>
{
Console.WriteLine("Program starts running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
var taskToRun = new Task(() =>
{
lock (lockObj)
{
for (int i = 0; i < 10; i++)
Console.WriteLine("{0} from Thread {1}",
i, Thread.CurrentThread.ManagedThreadId);
}
});
taskToRun.Start();
lock (lockObj)
{
taskToRun.Wait();
}
}).Wait() ;
}
}
/* Console output
Program starts running on thread 3
0 from Thread 3
1 from Thread 3
2 from Thread 3
3 from Thread 3
4 from Thread 3
5 from Thread 3
6 from Thread 3
7 from Thread 3
8 from Thread 3
9 from Thread 3
*/
No deadlock occured.
J. Richter wrote in his book "CLR via C#" 4th Edition on page 702:
When a thread calls the Wait method, the system checks if the Task that the thread is waiting for has started executing. If it has, then the thread calling Wait will block until the Task has completed running. But if the Task has not started executing yet, then the system may (depending on the TaskScheduler) execute the Trask by using the thread that called Wait. If this happens, then the thread calling Wait does not block; it executes the Task and returns immediatlely. This is good in that no thread has blocked, thereby reducing resource usage (by not creating a thread to replace the blocked thread) while improving performance (no time is spet to create a thread an there is no contexte switcing). But it can also be bad if, for example, thre thread has taken a thread synchronization lock before calling Wait and thren the Task tries to take the same lock, resulting in a deadlocked thread!
If I'm understand the paragraph correctly, the code above has to end in a deadlock!?
You're taking my usage of the word "lock" too literally. The C# "lock" statement (which my book discourages the use of), internally leverages Monitor.Enter/Exit. The Monitor lock is a lock that supports thread ownership & recursion. Therefore, a single thread can acquire this kind of lock multiple times successfully. But, if you use a different kind of lock, like a Semaphore(Slim), an AutoResetEvent(Slim) or a ReaderWriterLockSlim (without recursion), then when a single thread tries to acquire any of these locks multiple times, deadlock occurs.
In this example, you're dealing with task inlining, a not-so-rare behavior of the TPL's default task scheduler. It results in the task being executed on the same thread which is already waiting for it with Task.Wait(), rather than on a random pool thread. In which case, there is no deadlock.
Change your code like below and you'll have a dealock:
taskToRun.Start();
lock (lockObj)
{
//taskToRun.Wait();
((IAsyncResult)taskToRun).AsyncWaitHandle.WaitOne();
}
The task inlining is nondeterministic, it may or may not happen. You should make no assumptions. Check Task.Wait and “Inlining” by Stephen Toub for more details.
Updated, the lock does not affect the task inlining here. Your code still runs without deadlock if you move taskToRun.Start() inside the lock:
lock (lockObj)
{
taskToRun.Start();
taskToRun.Wait();
}
What does cause the inlining here is the circumstance that the main thread is calling taskToRun.Wait() right after taskToRun.Start(). Here's what happens behind the scene:
taskToRun.Start() queues the task for execution by the task scheduler, but it hasn't been allocated a pool thread yet.
On the same thread, the TPL code inside taskToRun.Wait() checks if the task has already been allocated a pool thread (it hasn't) and executes it inline on the main thread. In which case, it's OK to acquired the same lock twice without a deadlock.
There is also a TPL Task Scheduler thread. If this thread gets a chance to execute before taskToRun.Wait() is called on the main thread, inlining doesn't happen and you get a deadlock. Adding Thread.Sleep(100) before Task.Wait() would be modelling this scenario. Inlining also doesn't happen if you don't use Task.Wait() and rather use something like AsyncWaitHandle.WaitOne() above.
As to the quote you've added to your question, it depends on how you read it. One thing is for sure: the same lock from the main thread can be entered inside the task, when the task gets inlined, without a deadlock. You just cannot make any assumptions that it will get inlined.
In your example, no deadlock occurs because the thread scheduling the task and the thread executing the task happen to be the same. If you were to modify the code such that your task ran on a different thread, you would see the deadlock occur, because two threads would then be contending for a lock on the same object.
Your example, modified to create a deadlock:
class Program {
static object lockObj = new object();
static void Main(string[] args) {
Console.WriteLine("Program starts running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
var taskToRun = new Task(() => {
lock (lockObj) {
for (int i = 0; i < 10; i++)
Console.WriteLine("{0} from Thread {1}",
i, Thread.CurrentThread.ManagedThreadId);
}
});
lock (lockObj) {
taskToRun.Start();
taskToRun.Wait();
}
}
}
This example code has two standard threading problems. To understand it, you first have to understand thread races. When you start a thread, you can never assume it will start running right away. Nor can you assume that the code inside the thread arrives at a particular statement at a particular moment in time.
What matters a great deal here is whether or not the task arrives at the lock statement before the main thread does. In other words, whether it races ahead of the code in the main thread. Do model this as a horse race, the thread that acquired the lock is the horse that wins.
If it is the task that wins, pretty common on modern machines with multiple processor cores or a simple program that doesn't have any other threads active (and probably when you test the code) then nothing goes wrong. It acquires the lock and prevents the main thread from doing the same when it, later, arrives at the lock statement. So you'll see the console output, the task finishes, the main thread now acquires the lock and the Wait() call quickly completes.
But if the thread pool is already busy with other threads, or the machine is busy executing threads in other programs, or you are unlucky and you get an email just as the task starts running, then the code in the task doesn't start running right away and it is the main thread that acquired the lock first. The task can now no longer enter the lock statement so it cannot complete. And the main thread can not complete, Wait() will never return. A deadly embrace called deadlock.
Deadlock is relatively easy to debug, you've got all the time in the world to attach a debugger and look at the active threads to see why they are blocked. Threading race bugs are incredibly difficult to debug, they happen too infrequently and it can be very difficult to reason through the ordering problem that causes them. A common approach to diagnose thread races is to add tracing to the program so you can see the order. Which changes the timing and can make the bug disappear. Lots of programs were shipped with the tracing left on because they couldn't diagnose the problem :)
Thanks #jeffrey-richter for pointing it out, #embee there are scenario when we use locks other than Monitor than a single thread tries to acquire any of these locks multiple times, deadlock occurs. Check out the example below
The following code produce the expected deadlock. It need not be nested task the deadlock can occur without nesting also
class Program
{
static AutoResetEvent signalEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Task.Run(() =>
{
Console.WriteLine("Program starts running on thread {0}",
Thread.CurrentThread.ManagedThreadId);
var taskToRun = new Task(() =>
{
signalEvent.WaitOne();
for (int i = 0; i < 10; i++)
Console.WriteLine("{0} from Thread {1}",
i, Thread.CurrentThread.ManagedThreadId);
});
taskToRun.Start();
signalEvent.Set();
taskToRun.Wait();
}).Wait() ;
}
}
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);
}
}
}
}
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.
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.".
Read the Remarks section of the linked MSDN page:
When a thread calls Wait, it releases the lock on the object and enters the object's waiting queue. The next thread in the object's ready queue (if there is one) acquires the lock and has exclusive use of the object. All threads that call Wait remain in the waiting queue until they receive a signal from Pulse or PulseAll, sent by the owner of the lock. If Pulse is sent, only the thread at the head of the waiting queue is affected. If PulseAll is sent, all threads that are waiting for the object are affected. When the signal is received, one or more threads leave the waiting queue and enter the ready queue. A thread in the ready queue is permitted to reacquire the lock.
This method returns when the calling thread reacquires the lock on the object. Note that this method blocks indefinitely if the holder of the lock does not call Pulse or PulseAll.
So, basically, when you call Monitor.Wait, your thread is in the waiting queue. For it to re-acquire the lock, it needs to be in the ready queue. Monitor.Pulse moves the first thread in the waiting queue to the ready queue and thus allows for it to re-acquire the lock.
I find System.Monitor very confusing, although I understand threading, locks, deadlocks, race conditions, dining philosophers and all that jazz. Normally I use a ManualResetEvent() to do inter-thread co-ordination, but I know that that's a heavyweight kernel object, and that System.Monitor (Enter/Pulse, etc.) is much more efficient. I've Googled and Googled but cannot find a sensible example.
I would be most grateful if the SO crew could explain this potentially wonderful construct to me :-)
Here's a very simple example; the call to Wait releases the lock (allowing Worker to obtain it) and adds the Main thread to the lock-object's pending queue. Worker then obtains the lock, and calls Pulse: this moves the Main thread into the lock-object's ready queue. When Worker releases the lock, Main can resume work.
Note that lock(obj) {...} is just compiler-candy for Monitor.Enter/Monitor.Exit in a try/finally block.
[edit: I changed the sample to move lock(sync) earlier, to avoid the (unlikely) risk of a missed Pulse]
static void Main()
{
object sync = new object();
lock (sync)
{
ThreadPool.QueueUserWorkItem(Worker, sync);
Console.WriteLine("Main sleeping");
// wait for the worker to tell us it is ready
Monitor.Wait(sync);
Console.WriteLine("Main woke up!");
}
Console.WriteLine("Press any key...");
Console.ReadKey();
}
static void Worker(object sync)
{
Console.WriteLine("Worker started; about to sleep");
Thread.Sleep(5000);
Console.WriteLine("Worker about pulse");
lock (sync)
{ // notify Main that we did something interesting
Monitor.Pulse(sync);
Console.WriteLine("Worker pulsed; about to release lock");
}
Console.WriteLine("Worker all done");
}
See if this part of my threading article helps... (the second half of that page). It implements a producer/consumer queue: when the producer produces something in the queue (and finds it was empty - as an optimisation), it pulses the monitor to wake up any waiting threads. When a consumer tries to consume from the queue but finds it empty, it waits for a pulse before trying again.
Alternatively, Joe Albahari's threading tutorial has a section on Wait/Pulse too.
It's quite similar to the WaitHandle stuff you're used to - although frankly I find it easier to get my head round than WaitHandles, mostly because it's so similar to the Java wait/notify that I "grew up" with :)