一尘不染

内存屏障生成器

c#

阅读Joseph
Albahari的线程教程
,以下内容是内存障碍的产生者:

  • C#的lock声明(Monitor.Enter/ Monitor.Exit
  • Interlocked类上的所有方法
  • 使用线程池的异步回调-其中包括异步委托,APM回调和任务延续
  • 设置并等待信令构造
  • 任何依赖信令的内容,例如启动或等待任务

此外,Hans Passant和Brian Gideon
添加了以下内容(假设其中一个都不属于先前的类别之一):

  • 启动或唤醒线程
  • 上下文切换
  • Thread.Sleep()

我想知道这份清单是否完整(如果可以实际制作出完整的清单)

编辑 建议:

  • 易失性(阅读意味着获得范围,写作意味着释放范围)

阅读 406

收藏
2020-05-19

共1个答案

一尘不染

这是我对这个问题的看法,并试图在一个答案中提供一个准完整清单。如果遇到其他问题,我将不时编辑我的答案。

普遍认为会引起隐性障碍的机制:

  • 所有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规范没有强制性规定,但Microsoft对CLI的实现已在写入时释放了篱笆语义。
  • MarshalByRefObject似乎抑制了子类中的某些优化,这可能使其看起来好像存在隐式内存屏障。感谢Hans Passant发现此问题并将其引起我的注意。1个

1
这说明了为什么BackgroundWorker不用属性volatile的基础字段即可正确工作的原因CancellationPending

2020-05-19