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

Чтение и запись свойств атома в С#?

Чтение и запись некоторых примитивных типов в С#, таких как bool и int, являются атомарными.

(См. раздел 5.5, "5.5 Атомарность ссылок на переменные" в Спецификации языка С#.)

Но как насчет доступа к таким переменным через свойства? Можно ли предположить, что они также будут атомарными и потокобезопасными? Например. Является ли чтение MyProperty ниже атомарным и потокобезопасным?:

public bool MyProperty { get { return _foo; } }

А как насчет автоматически реализованных свойств?

public bool MyProperty { get; }
4b9b3361

Ответ 1

Вам нужно провести более четкое различие между "атомарным" и "потокобезопасным". Как вы говорите, записи являются атомарными для большинства встроенных типов значений и ссылок.

Однако это не значит, что они потокобезопасны. Это просто означает, что если значения "A" и "B" написаны, поток никогда не увидит что-то промежуточное. (например, изменение от 1 до 4 никогда не отображает 5 или 2 или любое значение, отличное от 1 или 4.) Это не означает, что один поток будет видеть значение "B", как только он будет записан в переменную. Для этого вам нужно взглянуть на модель памяти с точки зрения волатильности. Без барьеров памяти, обычно получаемых с помощью блокирующих и/или изменчивых переменных, запись в основную память может задерживаться, и считывания могут быть расширены, эффективно предполагая, что значение не изменилось с момента последнего чтения.

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

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

Ответ 2

Я немного не понимаю, что вы здесь задаете. Кажется, вы могли задавать 1 из 2 вопросов.

  • Является ли чтение _foo при вызове атома MyProperty?
  • Является ли возвращаемое значение MyProperty атомарным?

Для # 1 ответ да. Поскольку спецификация языка С# (и CLI) указывает, что чтение и запись переменных определенных определенных типов гарантированно будет атомарным. Тип "bool" является одним из этих типов.

Что касается №2, лучшим местом для просмотра является раздел 12.6.6 спецификации CLI. В нем указано, что

Соответствующий CLI должен гарантировать, что доступ для чтения и записи к правильно выровненным ячейкам памяти не превышает размер собственного слова (размер типа native int) - атомный

Учитывая использование возвращаемого значения MyProperty, вы должны либо читать, либо записывать значение, поэтому можно предположить, что оно задано атомарно.

Ответ 3

Если вы изучите автоматически сгенерированный код, вы увидите, что автоматически сгенерированные свойства НЕ являются потокобезопасными - они просто get/set для сгенерированного поля. На самом деле, это было бы слишком большим успехом, чтобы сделать это (особенно когда это не нужно).

Кроме того, если вы планируете получать значения int/bool из нескольких потоков, тогда вы должны пометить его (поле) как volatile, Это в основном предотвращает проблемы многопоточности, связанные с регистрами CPU. (Это помимо блокировки, а не альтернативы)

Ответ 4

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

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

Ответ 5

Я бы не подумал. Свойства - это, по сути, просто методы с немного синтаксического сахара на них, чтобы сделать их немного легче работать. Таким образом, по умолчанию они не более потокобезопасны, чем обычный вызов метода (то есть вообще не потокобезопасный).

Ответ 6

Вы можете поместить что-либо в свойство, например

    Public Property foo() As Boolean
        Get
           goToLunch()
           barbecueRibs()
           return m_foo
        End Get
        Set(ByVal value As Boolean)
           takeANap()
           accessDatabase()
           messUpOtherVariables()
           m_foo = value
        End Set
    End Property