Explanation about obtaining locks - c#

I have been coding with C# for a good little while, but this locking sequence does not make any sense to me. My understanding of locking is that once a lock is obtained with lock(object), the code has to exit the lock scope to unlock the object.
This brings me to the question at hand. I cut out the code below which happens to appear in an animation class in my code. The way the method works is that settings are passed to the method and modified and then passed to a another overloaded method. That other overloaded method will pass all the information to another thread to handle and actually animate the object in some way. When the animation completes, the other thread calls the OnComplete method. This actually all works perfectly, but I do not understand why!
The other thread is able to call OnComplete, obtain a lock on the object and signal to the original thread that it should continue. Should the code not freeze at this point since the object is held in a lock on another thread?
So this is not a need for help in fixing my code, it is a need for clarification on why it works. Any help in understanding is appreciated!
public void tween(string type, object to, JsDictionaryObject properties) {
// Settings class that has a delegate field OnComplete.
Tween.Settings settings = new Tween.Settings();
object wait_object = new object();
settings.OnComplete = () => {
// Why are we able to obtain a lock when the wait_object already has a lock below?
lock(wait_object) {
// Let the waiting thread know it is ok to continue now.
Monitor.Pulse(wait_object);
}
};
// Send settings to other thread and start the animation.
tween(type, null, to, settings);
// Obtain a lock to ensure that the wait object is in synchronous code.
lock(wait_object) {
// Wait here if the script tells us to. Time out with total duration time + one second to ensure that we actually DO progress.
Monitor.Wait(wait_object, settings.Duration + 1000);
}
}

As documented, Monitor.Wait releases the monitor it's called with. So by the time you try to acquire the lock in OnComplete, there won't be another thread holding the lock.
When the monitor is pulsed (or the call times out) it reacquires it before returning.
From the docs:
Releases the lock on an object and blocks the current thread until it reacquires the lock.

I wrote an article about this: Wait and Pulse demystified
There's more going on than meets the eye!

Remember that :
lock(someObj)
{
int uselessDemoCode = 3;
}
Is equivalent to:
Monitor.Enter(someObj);
try
{
int uselessDemoCode = 3;
}
finally
{
Monitor.Exit(someObj);
}
Actually there are variants of this that varies from version to version.
Already, it should be clear that we could mess with this with:
lock(someObj)
{
Monitor.Exit(someObj);
//Don't have the lock here!
Monitor.Enter(someObj);
//Have the lock again!
}
You might wonder why someone would do this, and well, so would I, it's a silly way to make code less clear and less reliable, but it does come into play when you want to use Pulse and Wait, which the version with explicit Enter and Exit calls makes clearer. Personally, I prefer to use them over lock if I'm going to Pulse or Wait for that reason; I find that lock stops making code cleaner and starts making it opaque.

I tend to avoid this style, but, as Jon already said, Monitor.Wait releases the monitor it's called with, so there is no locking at that point.
But the example is slightly flawed IMHO. The problem is, generally, that if Monitor.Pulse gets called before Monitor.Wait, the waiting thread will never be signaled. Having that in mind, the author decided to "play safe" and used an overload which specified a timeout. So, putting aside the unnecessary acquiring and releasing of the lock, the code just doesn't feel right.
To explain this better, consider the following modification:
public static void tween()
{
object wait_object = new object();
Action OnComplete = () =>
{
lock (wait_object)
{
Monitor.Pulse(wait_object);
}
};
// let's say that a background thread
// finished really quickly here
OnComplete();
lock (wait_object)
{
// this will wait for a Pulse indefinitely
Monitor.Wait(wait_object);
}
}
If OnComplete gets called before the lock is acquired in the main thread, and there is no timeout, we will get a deadlock. In your case, Monitor.Wait will simply hang for a while and continue after a timeout, but you get the idea.
That is why I usually recommend a simpler approach:
public static void tween()
{
using (AutoResetEvent evt = new AutoResetEvent(false))
{
Action OnComplete = () => evt.Set();
// let's say that a background thread
// finished really quickly here
OnComplete();
// event is properly set even in this case
evt.WaitOne();
}
}
To quote MSDN:
The Monitor class does not maintain state indicating that the Pulse method has been called. Thus, if you call Pulse when no threads are waiting, the next thread that calls Wait blocks as if Pulse had never been called. If two threads are using Pulse and Wait to interact, this could result in a deadlock.
Contrast this with the behavior of the AutoResetEvent class: If you signal an AutoResetEvent by calling its Set method, and there are no threads waiting, the AutoResetEvent remains in a signaled state until a thread calls WaitOne, WaitAny, or WaitAll. The AutoResetEvent releases that thread and returns to the unsignaled state.

Related

How do I find the other threads that send back the signal when one thread calls WaitOne?

One of the things I'm having a hard time to understand in multi-threaded programming is that fact that when one thread reaches a line that calls WaitOne(), how do I know which other threads are involved? Where or how can I find (or understand) how the WaitHandle receives the signal? For example, I'm looking at this code right now:
private void RunSync(object state, ElapsedEventArgs elapsedEventArgs)
{
_mutex.WaitOne();
using (var sync = GWSSync.BuildSynchronizer(_log))
{
try
{
sync.Syncronize();
}
catch(Exception ex)
{
_log.Write(string.Format("Error during synchronization : {0}", ex));
}
}
_mutex.ReleaseMutex();
_syncTimer.Interval = TimeBeforeNextSync().TotalMilliseconds;
_syncTimer.Start();
}
There are a few methods like this in the file (i.e RunThis(), RunThat()). These methods run inside a Windows service and are called when a Timer elapses. Each of these methods are called using different Timers and set up like this:
//Synchro
var timeBeforeFirstSync = TimeBeforeNextSync();
_syncTimer = new System.Timers.Timer(timeBeforeFirstSync.TotalMilliseconds);
_syncTimer.AutoReset = false;
_syncTimer.Elapsed += RunSync;
_syncTimer.Start();
I understand that when the Timer elapses, the RunSync method will run. But when it hits the WaitOne() line, the thread is blocked. But who is it waiting for? Which "other" thread will send the signal?
WaitHandle is an abstraction, as stated in the documentation:
Encapsulates operating system–specific objects that wait for exclusive access to shared resources.
You don't know which other threads are involved, but you do know which other code is involved by checking the usage of the handle (_mutex in your case). Every WaitHandle derived class inherits WaitOne, but what happens after successful wait and how it's get signalled is specific. For instance, in your example _mutex most probably is a Mutex class, so WaitOne acts like "wait until it's free and take ownership" while the ReleaseMutex acts like "release ownership and signal". With that in mind, it should be obvious what all these methods do - ensuring that while RunThis you cannot RunThat and vise versa.

Dispose WaitHandle for basic thread synchronization

According to documentation, WaitHandle in .NET should be explicitly/implicitly disposed. However, I'm having trouble achieving this for the following basic synchronization task:
a time consuming task is being executed on a thread.
the main thread waits for the task to complete for a predefined time-period. The main thread must proceed if a. the task is completed or b. the timeout occurred.
Here my attempt at using an AutoResetEvent object:
using(var waitHandle = new AutoResetEvent(false)){
var worker = new Thread(() =>
{
try
{
TimeConsumingTask();
waitHandle.Set(); //throws System.ObjectDisposedException: Safe handle has been closed
}
catch (Exception e)
{...}
}) {IsBackground = true};
worker.Start(); //start worker
const int waitTimeInMs = 5000;
var signaled = waitHandle.WaitOne(waitTimeInMs);//block main thread here.
if (!signaled)
{ //if timed out
worker.Interrupt();
}
}
There is an obvious race condition where the main thread wait times out and disposes the wait handle object which causes ObjectDisposedException exception. Is there any other way that I set this up so that the handle is properly disposed and without causing the exception?
Sure, there's no decent way to do this. Do note up front that you painted yourself into that corner by essentially leaving a thread running wild, nothing particularly nice about that.
But you are focusing on the much smaller problem. The Thread class itself is already a resource hog, consuming a megabyte of VM and five synchronization objects. But it has no Dispose() method. This was courageous design, there's just no decent way to call the method.
Disposing is optional, nothing that dramatic happens when you don't call it. The class has got your back, it has a finalizer that ensures that the native operating system resource will be released. Which will run, eventually, just not as quickly as you'd like.
Compare this to a class with a less courageous design, the Task class has a Dispose() method. Which, like Thread, is almost as hard to call. The guidance from the .NET gurus is to just not bother.
Same here.
The waithandle is disposing because your using scope invokes a new thread an returns immediately, causing the waithandle to dispose.
What you should do is explicitly call dispose after you finish your work instead of your using statement:
waitHandle.WaitOne(waitTimeInMs);
if (!signaled)
{ //if timed out
worker.Interrupt();
}
waitHandle.Dispose();

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);
}
}
}
}
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.

Wait for a thread to actually start in c#

I need to start a thread, but continue just after the thread is actually running. Now my code looks like:
splashthread.IsBackground = false;
splashthread.Start();
Thread.Sleep(100); // Wait for the thread to start
I'm not fond of these voodoo sleeps (to say the least), so I'm looking for more nifty way of doing the above.
Any ideas?
Something like this:
var splashStart = new ManualResetEvent(false);
var splashthread = new Thread(
() =>
{
splashStart.Set();
// Your thread code here...
});
splashthread.Start();
splashStart.WaitOne();
Don't forget to Dipose splashStart or if it's appropriate in your code use a using block.
Edit: Didn't confirm the original code in the IDE. Changed Wait to WaitOne() as per comment below.
Why do you care when the other thread starts? You well may be interested in knowing when the new thread has reached some particular milestone, and you could use any number of synchronization primitives to deal with that (in addition to events, if the new thread is going to be initializing something visible to the constructing thread, you could use a monitor lock with Monitor.Wait/Monitor.Pulse. Monitor locks are lightweight, but require a little care.
In particular, the thread which is going to wait for the other thread must check within a synclock whether the object has been initialized, before it does Monitor.Wait. Otherwise it's possible that the new thread might perform its Monitor.Pulse before the main thread has reached its Monitor.Wait. Adding the object-initialized check would prevent that scenario. If the new thread hasn't initialized the object before the launcher thread entered the synclock to check and wait, it won't be able to perform the Pulse until after the launcher thread gives up its lock via Monitor.Wait. If the new thread has initialized the object before the launcher thread entered the synclock, the launcher thread will see that and not wait at all.

c#: what is a thread polling?

What does it mean when one says no polling is allowed when implimenting your thread solution since it's wasteful, it has latency and it's non-deterministic. Threads should not use polling to signal each other.
EDIT
Based on your answers so far, I believe my threading implementation (taken from: http://www.albahari.com/threading/part2.aspx#_AutoResetEvent) below is not using polling. Please correct me if I am wrong.
using System;
using System.Threading;
using System.Collections.Generic;
class ProducerConsumerQueue : IDisposable {
EventWaitHandle _wh = new AutoResetEvent (false);
Thread _worker;
readonly object _locker = new object();
Queue<string> _tasks = new Queue<string>();
public ProducerConsumerQueue() (
_worker = new Thread (Work);
_worker.Start();
}
public void EnqueueTask (string task) (
lock (_locker) _tasks.Enqueue (task);
_wh.Set();
}
public void Dispose() (
EnqueueTask (null); // Signal the consumer to exit.
_worker.Join(); // Wait for the consumer's thread to finish.
_wh.Close(); // Release any OS resources.
}
void Work() (
while (true)
{
string task = null;
lock (_locker)
if (_tasks.Count > 0)
{
task = _tasks.Dequeue();
if (task == null) return;
}
if (task != null)
{
Console.WriteLine ("Performing task: " + task);
Thread.Sleep (1000); // simulate work...
}
else
_wh.WaitOne(); // No more tasks - wait for a signal
}
}
}
Your question is very unclear, but typically "polling" refers to periodically checking for a condition, or sampling a value. For example:
while (true)
{
Task task = GetNextTask();
if (task != null)
{
task.Execute();
}
else
{
Thread.Sleep(5000); // Avoid tight-looping
}
}
Just sleeping is a relatively inefficient way of doing this - it's better if there's some coordination so that the thread can wake up immediately when something interesting happens, e.g. via Monitor.Wait/Pulse or Manual/AutoResetEvent... but depending on the context, that's not always possible.
In some contexts you may not want the thread to actually sleep - you may want it to become available for other work. For example, you might use a Timer of one sort or other to periodically poll a mailbox to see whether there's any incoming mail - but you don't need the thread to actually be sleeping when it's not checking; it can be reused by another thread-pool task.
Here you go: check out this website:
http://msdn.microsoft.com/en-us/library/dsw9f9ts%28VS.71%29.aspx
Synchronization Techniques
There are two approaches to synchronization, polling and using synchronization objects. Polling repeatedly checks the status of an asynchronous call from within a loop. Polling is the least efficient way to manage threads because it wastes resources by repeatedly checking the status of the various thread properties.
For example, the IsAlive property can be used when polling to see if a thread has exited. Use this property with caution because a thread that is alive is not necessarily running. You can use the thread's ThreadState property to get more detailed information about a thread's status. Because threads can be in more than one state at any given time, the value stored in ThreadState can be a combination of the values in the System.Threading.Threadstate enumeration. Consequently, you should carefully check all relevant thread states when polling. For example, if a thread's state indicates that it is not Running, it may be done. On the other hand, it may be suspended or sleeping.
Waiting for a Thread to Finish
The Thread.Join method is useful for determining if a thread has completed before starting another task. The Join method waits a specified amount of time for a thread to end. If the thread ends before the timeout, Join returns True; otherwise it returns False. For information on Join, see Thread.Join Method
Polling sacrifices many of the advantages of multithreading in return for control over the order that threads run. Because it is so inefficient, polling generally not recommended. A more efficient approach would use the Join method to control threads. Join causes a calling procedure to wait either until a thread is done or until the call times out if a timeout is specified. The name, join, is based on the idea that creating a new thread is a fork in the execution path. You use Join to merge separate execution paths into a single thread again
One point should be clear: Join is a synchronous or blocking call. Once you call Join or a wait method of a wait handle, the calling procedure stops and waits for the thread to signal that it is done.
Copy
Sub JoinThreads()
Dim Thread1 As New System.Threading.Thread(AddressOf SomeTask)
Thread1.Start()
Thread1.Join() ' Wait for the thread to finish.
MsgBox("Thread is done")
End Sub
These simple ways of controlling threads, which are useful when you are managing a small number of threads, are difficult to use with large projects. The next section discusses some advanced techniques you can use to synchronize threads.
Hope this helps.
PK
Polling can be used in reference to the four asyncronous patterns .NET uses for delegate execution.
The 4 types (I've taken these descriptions from this well explained answer) are:
Polling: waiting in a loop for IAsyncResult.Completed to be true
I'll call you
You call me
I don't care what happens (fire and forget)
So for an example of 1:
Action<IAsyncResult> myAction = (IAsyncResult ar) =>
{
// Send Nigerian Prince emails
Console.WriteLine("Starting task");
Thread.Sleep(2000);
// Finished
Console.WriteLine("Finished task");
};
IAsyncResult result = myAction.BeginInvoke(null,null,null);
while (!result.IsCompleted)
{
// Do something while you wait
Console.WriteLine("I'm waiting...");
}
There's alternative ways of polling, but in general it means "I we there yet", "I we there yet", "I we there yet"
What does it mean when one says no
polling is allowed when implimenting
your thread solution since it's
wasteful, it has latency and it's
non-deterministic. Threads should not
use polling to signal each other.
I would have to see the context in which this statement was made to express an opinion on it either way. However, taken as-is it is patently false. Polling is a very common and very accepted strategy for signaling threads.
Pretty much all lock-free thread signaling strategies use polling in some form or another. This is clearly evident in how these strategies typically spin around in a loop until a certain condition is met.
The most frequently used scenario is the case of signaling a worker thread that it is time to terminate. The worker thread will periodically poll a bool flag at safe points to see if a shutdown was requested.
private volatile bool shutdownRequested;
void WorkerThread()
{
while (true)
{
// Do some work here.
// This is a safe point so see if a shutdown was requested.
if (shutdownRequested) break;
// Do some more work here.
}
}

Categories