Блокировка геттера и сеттера булевых свойств
Есть ли какая-либо причина, по которой вы создаете блокировки вокруг геттера и сеттера логического свойства, подобного этому?
private _lockObject = new object();
private bool _myFlag;
public bool MyFlag
{
get
{
lock (_lockObject)
{
return _myFlag;
}
}
set
{
lock (_lockObject)
{
_myFlag = value;
}
}
}
3 ответов:
Ну, вам не обязательно нужны блокировки - но если вы хотите, чтобы один поток определенно прочитал значение, которое записал другой поток, вам нужны либо блокировки, либо переменная volatile.
Я лично отказался от попыток понять точное значение слова volatile. Я стараюсь избегать написания собственного кода без блокировки, вместо этого полагаясь на экспертов, которые действительно понимают модель памяти.EDIT: в качестве примера проблемы, которую это может вызвать, рассмотрим следующее код:
using System; using System.Threading; public class Test { private static bool stop = false; private bool Stop { get { return stop; } set { stop = value; } } private static void Main() { Thread t = new Thread(DoWork); t.Start(); Thread.Sleep(1000); // Let it get started Console.WriteLine("Setting stop flag"); Stop = true; Console.WriteLine("Set"); t.Join(); } private static void DoWork() { Console.WriteLine("Tight looping..."); while (!Stop) { } Console.WriteLine("Done."); } }Эта программа может или не может завершиться. Я видел и то, и другое. Нет никакой гарантии, что поток" чтения " будет На самом деле Читать из основной памяти - он может поместить начальное значение
stopв регистр и просто продолжать использовать его вечно. Я видел, как это происходит на самом деле. Этого не происходит на моих текущих машинах, но это может произойти на моих следующих.Установка блокировок в геттере/сеттере свойств в соответствии с кодом в вопросе сделает этот код правильное и предсказуемое его поведение.
Подробнее об этом смотрите в этом блоге Эрика Липперта.
Чтение и запись bool являются атомный.
Однако имя "флаг" указывает на то, что отдельные потоки будут читать/записывать, пока не возникнет некоторое условие. Чтобы избежать неожиданного поведения Из-за оптимизации, вы должны рассмотреть возможность добавления ключевого слова
volatileк объявлению bool.
Нет никакой причины иметь замок прямо там.
Взятие замка вполне может быть уместным в вашем дизайне, но очень сомнительно, что это правильная детализация.
Вам нужно сделать свой дизайн потокобезопасным, а не отдельные свойства (или даже целые объекты).
Comments