Подтвердить что ты не робот

Должна ли переменная блокировки быть измененной?

У меня есть следующая инструкция Lock:

private readonly object ownerLock_ = new object();

lock (ownerLock_)
{
}

Должен ли я использовать volatile ключевое слово для моей переменной блокировки?

private readonly volatile object ownerLock_ = new object();

В MSDN я видел, что он обычно используется для поля, к которому обращаются без блокировки, поэтому, если я использую Lock, мне не нужно использовать volatile?

От MSDN:

Модификатор volatile обычно используется для поля, к которому осуществляется доступ несколько потоков без использования оператора блокировки для сериализации доступа.

4b9b3361

Ответ 1

Если вы только когда-либо обращаетесь к данным, которые блокируют "охранники", когда вы владеете блокировкой, тогда да - сделать эти поля неустойчивыми излишними. Вам не нужно также изменять переменную ownerLock_. (В настоящий момент в операторе lock вы не указали какой-либо фактический код, что затрудняет разговор в конкретных терминах - но я предполагаю, что вы действительно будете читать/изменять некоторые данные в инструкции lock. )

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

Я бы только ожидал увидеть volatile внутри кода, который пытается создать абстракции более высокого уровня для потоковой передачи - например, в базе кода TPL. Это действительно инструмент для экспертов, которые действительно хорошо понимают модель памяти .NET... из которых их очень мало, ИМО.

Ответ 2

Если что-то есть readonly, это поточно-безопасное, период. (Ну, почти. Эксперт может выяснить, как получить исключение NullReferenceException в вашем lock, но это будет непросто.) С readonly вам не нужны volatile, Interlocked, или блокировки. Это идеальное ключевое слово для многопоточности, и вы должны использовать его там, где сможете. Он отлично работает для объекта блокировки, где его большой недостаток (вы не можете изменить значение) не имеет значения.

Кроме того, в то время как ссылка является неизменной, ссылка на объект не может быть. "new object()" здесь, но если это был List или что-то другое, изменяемое, а не потокобезопасное, вы хотели бы заблокировать ссылку (и все другие ссылки на нее, если таковые имеются), чтобы сохранить объект меняется одновременно на два потока.