Ответ 1
Вот мой вопрос по этому вопросу и попытка представить квазиполный список в одном ответе. Если я буду сталкиваться с любыми другими, я время от времени буду изменять свой ответ.
Механизмы, которые в целом согласованы, чтобы вызвать неявные барьеры:
- Все методы класса
Monitor
, включая ключевое слово С#lock
- Все методы класса
Interlocked
. - Все методы класса
Volatile
(.NET 4.5 +). - Большинство методов
SpinLock
, включаяEnter
иExit
. -
Thread.Join
-
Thread.VolatileRead
иThread.VolatileWrite
-
Thread.MemoryBarrier
- Ключевое слово
Volatile
. - Все, что запускает поток или заставляет делегата выполнять другой поток, включая
QueueUserWorkItem
,Task.Factory.StartNew
,Thread.Start
, компилятор предоставил методыBeginInvoke
и т.д. - Использование механизма сигнализации, такого как
ManualResetEvent
,AutoResetEvent
,CountdownEvent
,Semaphore
,Barrier
и т.д. - Использование операций маршалинга, таких как
Control.Invoke
,Dispatcher.Invoke
,SynchronizationContext.Post
и т.д.
Механизмы, которые предположительно (но не известные наверняка) вызывают неявные барьеры:
-
Thread.Sleep
(предложенный мной и, возможно, другими из-за того, что этот код, который обнаруживает проблему с барьером памяти, может быть исправлен с помощью этого метода) -
Thread.Yield
-
Thread.SpinWait
-
Lazy<T>
, в зависимости от которогоLazyThreadSafetyMode
указан
Другие примечательные упоминания:
- По умолчанию добавляются и удаляются обработчики для событий на С#, поскольку они используют
lock
илиInterlocked.CompareExchange
. - В магазинах x86 есть семантика релизной решетки
- В реализации Microsoft CLI предусмотрена семантика выпусков релиза, несмотря на то, что спецификация ECMA не предусматривает ее.
-
MarshalByRefObject
, кажется, подавляет определенные оптимизации в подклассах, которые могут казаться похожими на неявный барьер памяти. Спасибо Hans Passant за то, что вы открыли это и привлекли мое внимание. 1
1 Это объясняет, почему BackgroundWorker
работает правильно, не имея Volatile
в базовом поле для свойства CancellationPending
.