Вопрос

Действительно ли этот шаблон взаимного исключения так безопасен, как я думаю?Если да, то как вы это называете?

lock (_lock) {
    if (_flag) return;
    else _flag = true;
}
try {
    //critical code...
}
finally {
    _flag = false;
}

Я хочу обеспечить критическую секцию, но без скопления других потоков, ожидающих получения блокировки.Очевидно, я слежу за тем, чтобы флаг больше нигде не был установлен.Есть ли лучший способ?

Это было полезно?

Решение

Нет, это небезопасно.Если вы хотите обеспечить взаимоисключающие действия без блокировки, вы можете использовать Monitor.Попробуйте ввести:

if (Monitor.TryEnter(lockObj, 0)) {
    // got the lock !
    try {
        // code
    }
    finally { // release the lock
        Monitor.Exit(lockObj);
    }
}

Другие советы

Вы смотрели на Monitor.TryEnter?

Корректность вашего шаблона взаимного исключения зависит от того, является ли присвоение _flag=false атомарным.Представьте, что бы произошло, если бы задание могло быть прервано другим потоком.Если промежуточные результаты задания могут быть интерпретированы тестом как false, одно задание может привести к тому, что несколько потоков войдут в критическую секцию.

Корректность шаблона взаимного исключения также зависит от отсутствия оптимизаций в компиляторе, которые могут изменить порядок инструкций.Представьте себе "умный" компилятор, который переместил бы присваивание _flag=false вверх, потому что _flag не упоминается в промежуточном коде (а промежуточный код не генерирует исключений).Затем компилятор мог бы оптимизировать часть в разделе блокировки для чтения

if(_flag) return;

Оба примера того, почему паттерн может дать сбой, носят весьма умозрительный характер, и я думаю, что вы можете с уверенностью предположить, что он работает.Однако при наличии другого варианта, который работает по мере необходимости, вам лучше использовать его (см. Другие сообщения).Если в том же коде есть другие разработчики, им не нужно рассматривать, работает ли шаблон.

Не было бы простого lock(Object) заявление работает?За кулисами это создает Monitor и критический раздел внутри try... finally блок.

private static readonly Object lockMe = new Object();
lock(lockMe)
{
    // critical code
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top