Блокировка одной переменной bool при многопоточности?
Недавно я видел этот код в WebSite, и мой вопрос следующий:
private bool mbTestFinished = false;
private bool IsFinished()
{
lock( mLock )
{
return mbTestFinished;
}
}
internal void SetFinished()
{
lock( mLock )
{
mbTestFinished = true;
}
}
В многопоточной среде действительно необходимо заблокировать доступ к mbTestFinished
?
Ответы
Ответ 1
Да, это необходимо..Net использует некоторые оптимизации, и иногда, если к памяти часто обращаются, данные перемещаются в регистры CPU. Итак, в этом случае, если mbTestFinished находится в регистре CPU, тогда поток, читающий его, может получить неправильное значение. Таким образом, использование энергозависимого ключа гарантирует, что все обращения к этой переменной выполняются в памяти, а не в регистрах.
С другой стороны, я не имею представления о частоте этого появления. Это может происходить на очень низкой частоте.
Ответ 2
По-моему, нет, замок здесь лишний, по двум причинам:
- Булевы переменные не могут вызвать разрывание назначения, например,
long
, поэтому блокировка не требуется.
- Для решения проблемы видимости
volatile
достаточно. Верно, что lock
вводит неявный забор, но так как lock
не требуется для атомарности, volatile
достаточно.
Ответ 3
Если mLock ТОЛЬКО для переменной mbTestFinished, то это немного перебор. Вместо этого вы можете использовать volatile или Interlocked, потому что обе являются конструкциями пользовательского режима для синхронизации потоков. блокировка (или Монитор) представляет собой гибридную конструкцию в том смысле, что она хорошо оптимизирована, чтобы избежать перехода от/к режиму ядра, когда это возможно. В книге "CLR via С#" содержится подробное обсуждение этих концепций.