Примечание: Я ограничен .NET 3.5, поэтому я не могу использовать ManualResetEventSlim
.Может ли EventWaitHandle иметь дело с ложными следами?
Должен ли я иметь дело с Spurious wakeups, делая что-то вроде этого:
var waitHandle = new EventWaitHandle();
new Thread(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(5));
waitHandler.Set();
});
waitHandle.WaitOne();
Если да, то правильный барьер памяти устанавливается при вызове Set
и/или WaitOne
таким образом, что это будет безопасно:
var reallyDone = false;
var waitHandle = new EventWaitHandle();
new Thread(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(5));
reallyDone = true;
waitHandler.Set();
});
while (!reallyDone)
waitHandle.WaitOne();
В частности, возможно ли, что основной поток в этом примере может не увидеть, что reallyDone
установлено в true из-за переупорядочения или кеширования команд? reallyDone
должен быть неустойчивым в этом случае или это не нужно?
Нет побочных пробуждений. Почти все программы для Windows сломались, если бы это было так. Вы сражаетесь с ветряными мельницами. Но да, функции синхронизации выполняют полный барьер памяти (который хорошо понимается, но нигде не документируется). – usr
Я не согласен: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682052%28v=vs.85%29.aspx «Переменные условия подвержены ложным пробуждениям (те, которые не связаны с явным следом) и украденные пробуждения (другой поток удается запустить до разбуженного потока). Поэтому вам нужно перепроверить предикат (обычно в цикле while) после возвращения операции сна. " Также в .NET 4.0+ есть такой код: http://referencesource.microsoft.com/#mscorlib/system/threading/ManualResetEventSlim.cs,635 «// Loop для обработки ложных пробуждений от других ожиданий, которые будут отменены " –
Событие не является переменной условия. Это не относится. Исходный код сообщает вам, что инфраструктура обрабатывает этот случай для вас. Поддельные пробуждения не подвержены коду пользователя. Это детали реализации, которые вы там выкопали. – usr