Блокировка геттера и сеттера булевых свойств



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



  private _lockObject = new object();
private bool _myFlag;
public bool MyFlag
{
get
{
lock (_lockObject)
{
return _myFlag;
}
}
set
{
lock (_lockObject)
{
_myFlag = value;
}
}
}
585   3  

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

    Ничего не найдено.