Нужна ли блокировка, если у меня есть EventWaitHandle
Изучение многопоточности из предсердия альбахари. Мне нужен замок _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);
}
}
}
}
2 ответа
Ты прав.
Такие проблемы не могут быть просто проверены методом проб и ошибок. Их лучше всего анализировать с помощью логического мышления:
- Какой поток выполняет какой код?
- Что может произойти в другом потоке прямо сейчас?
- Что произойдет, если другой поток получит больше процессорного времени? и т.п.
Основной поток будет выполнять код только в Main()
и рабочий поток будет выполнять код только в Work()
, Это достаточно просто.
Если вы посмотрите, как осуществляется доступ к критическому ресурсу, вы заметите, что доступ к _message
в Main()
всегда между
_ready.WaitOne();
а также
_go.Set();
тогда как доступ к _message
в Work()
всегда между
_go.WaitOne();
а также
_ready.Set();
Таким образом, один из потоков всегда будет ждать другого, прежде чем получить доступ _message
и замок не нужен.
Вы остановили ваши темы от доступа к _message
переменная в то же время. Ваша логика здесь самодостаточна и предсказуема, что не всегда так. иногда вы будете читать из других мест, и поток не будет полностью управляемым, и в этом случае вам нужно будет заблокировать критические переменные.