Studying multi-threading from albahari atricle.
Do I need a lock _locker
in the sample below? I suppose no, since _message
is protected by EventWaitHandle
. Am I right?
class TwoWaySignaling
{
static EventWaitHandle _ready = new AutoResetEvent (false);
static EventWaitHandle _go = new AutoResetEvent (false);
static readonly object _locker = new object();
static string _message;
static void Main()
{
new Thread (Work).Start();
_ready.WaitOne(); // First wait until worker is ready
lock (_locker) _message = "ooo";
_go.Set(); // Tell worker to go
_ready.WaitOne();
lock (_locker) _message = "ahhh"; // Give the worker another message
_go.Set();
_ready.WaitOne();
lock (_locker) _message = null; // Signal the worker to exit
_go.Set();
}
static void Work()
{
while (true)
{
_ready.Set(); // Indicate that we're ready
_go.WaitOne(); // Wait to be kicked off...
lock (_locker)
{
if (_message == null) return; // Gracefully exit
Console.WriteLine (_message);
}
}
}
}
You are correct.
These kind of problems cannot be simply tested with trial and error. They are best analyzed with logical thinking:
The main thread will only execute the code in Main()
and the worker thread will only execute the code in Work()
. So that's simple enough.
If you look at how the critical resource is accessed you will note that access to _message
in Main()
is always between
_ready.WaitOne();
and
_go.Set();
whereas access to _message
in Work()
is always between
_go.WaitOne();
and
_ready.Set();
Therefore, one of the threads will always wait for the other before accessing _message
and the lock is not needed.