Являются ли свойства чтения и записи атомарными в C #? - PullRequest
20 голосов
/ 20 июля 2009

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

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

Но как насчет доступа к таким переменным через свойства? Разумно ли предположить, что они также будут атомарными и поточно-ориентированными? Например. Чтение MyProperty ниже атомного и поточно-ориентированного?

public bool MyProperty { get { return _foo; } }

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

public bool MyProperty { get; }

Ответы [ 6 ]

29 голосов
/ 20 июля 2009

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

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

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

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

2 голосов
/ 20 июля 2009

Мне немного непонятно, о чем вы спрашиваете здесь. Похоже, вы могли бы задать 1 из 2 вопросов

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

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

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

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

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

1 голос
/ 20 июля 2009

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

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

1 голос
/ 20 июля 2009

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

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

0 голосов
/ 20 июля 2009

Вы можете поместить что угодно в свойство, например,

    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
0 голосов
/ 20 июля 2009

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

...