如果我有 EventWaitHandle,我需要锁吗
Do I need a lock if I have EventWaitHandle
从albahari atricle开始研究多线程。
我需要在下面的示例中使用锁 _locker
吗?我想不会,因为 _message
受到 EventWaitHandle
的保护。我说得对吗?
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);
}
}
}
}
你是对的。
这类问题不能简单地通过反复试验来测试。最好用逻辑思维来分析它们:
- 哪个线程运行哪个代码?
- 另一个线程现在会发生什么?
- 如果另一个线程获得更多 CPU 时间会怎样?等等
主线程只会执行Main()
中的代码,工作线程只会执行Work()
中的代码。所以这很简单。
如果您查看关键资源的访问方式,您会注意到 Main()
中对 _message
的访问始终介于
之间
_ready.WaitOne();
和
_go.Set();
而在 Work()
中访问 _message
总是在
之间
_go.WaitOne();
和
_ready.Set();
因此,其中一个线程在访问 _message
之前将始终等待另一个线程,因此不需要锁。
您阻止线程同时访问 _message
变量。您的逻辑在这里是自给自足且可预测的,但情况并非总是如此。有时你会从其他地方读取并且流程不是完全可控的,在这种情况下你需要锁定关键变量。
从albahari atricle开始研究多线程。
我需要在下面的示例中使用锁 _locker
吗?我想不会,因为 _message
受到 EventWaitHandle
的保护。我说得对吗?
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);
}
}
}
}
你是对的。
这类问题不能简单地通过反复试验来测试。最好用逻辑思维来分析它们:
- 哪个线程运行哪个代码?
- 另一个线程现在会发生什么?
- 如果另一个线程获得更多 CPU 时间会怎样?等等
主线程只会执行Main()
中的代码,工作线程只会执行Work()
中的代码。所以这很简单。
如果您查看关键资源的访问方式,您会注意到 Main()
中对 _message
的访问始终介于
_ready.WaitOne();
和
_go.Set();
而在 Work()
中访问 _message
总是在
_go.WaitOne();
和
_ready.Set();
因此,其中一个线程在访问 _message
之前将始终等待另一个线程,因此不需要锁。
您阻止线程同时访问 _message
变量。您的逻辑在这里是自给自足且可预测的,但情况并非总是如此。有时你会从其他地方读取并且流程不是完全可控的,在这种情况下你需要锁定关键变量。