c# - visual - vs2017 15.9 3




內存屏障生成器 (2)

閱讀Joseph Albahari的線程教程 ,以下內容被提及作為內存屏障的生成器:

  • C#的lock語句( Monitor.Enter / Monitor.Exit
  • Interlocked類的所有方法
  • 使用線程池的異步回調 - 包括異步委託,APM回調和任務延續
  • 設置和等待信令構造
  • 任何依賴於信令的東西,例如啟動或等待任務

此外,Hans Passant和Brian Gideon 補充了以下內容 (假設其中沒有一個已經適合以前的類別之一):

  • 啟動或喚醒線程
  • 上下文切換
  • Thread.Sleep()

我想知道這個清單是否完整(如果完整清單甚至可以實際製作)

編輯添加建議:

  • 易失性(讀數意味著獲取圍欄,寫作意味著釋放圍欄)


以下是我對該主題的看法,並嘗試在一個答案中提供準完整列表。 如果我遇到任何其他人,我會不時編輯我的答案。

普遍認為會導致隱含障礙的機制:

  • 所有Monitor類方法包括C#關鍵字lock
  • 所有Interlocked類方法。
  • 所有Volatile類方法(.NET 4.5+)。
  • 大多數SpinLock方法包括EnterExit
  • Thread.Join
  • Thread.VolatileReadThread.VolatileWrite
  • Thread.MemoryBarrier
  • volatile關鍵字。
  • 任何啟動線程或導致委託在另一個線程上執行的東西,包括QueueUserWorkItemTask.Factory.StartNewThread.Start ,編譯器提供的BeginInvoke方法等。
  • 使用信號機制,如ManualResetEventAutoResetEventCountdownEventSemaphoreBarrier等。
  • 使用編組操作,如Control.InvokeDispatcher.InvokeSynchronizationContext.Post等。

被推測(但不確定)導致隱含障礙的機制:

  • Thread.Sleep (由我自己和其他人提出,因為可以用這種方法修復出現內存屏障問題的代碼)
  • Thread.Yield
  • Thread.SpinWait
  • Lazy<T>取決於指定的LazyThreadSafetyMode

其他值得注意的提及:

  • 默認添加和刪除C#中事件的處理程序,因為它們使用lockInterlocked.CompareExchange
  • x86商店有發布範圍語義
  • 儘管ECMA規範沒有強制要求,但微軟實施的CLI在寫入時具有發布範圍語義。
  • MarshalByRefObject似乎抑制了子類中的某些優化,這可能使它看起來好像存在隱式內存屏障。 感謝Hans Passant發現這一點並引起我的注意。 1

1 這解釋了為什麼BackgroundWorkerCancellationPending屬性的基礎字段上沒有volatile的情況下正常工作的原因。





memory-barriers