内存屏障生成器

发布于 2024-11-18 21:33:16 字数 757 浏览 4 评论 0原文

阅读 Joseph Albahari 的线程教程,提到以下内容作为内存屏障的生成器:

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

此外,Hans Passant 和 Brian Gideon 添加了以下内容(假设其中没有一个适合其中之一)前面的类别):

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

我想知道这个列表是否完整(如果实际上可以制作完整的列表)

编辑

  • 易失性(读取意味着获取栅栏,写入意味着释放栅栏)

Reading Joseph Albahari's threading tutorial, the following are mentioned as generators of memory barriers:

  • C#'s lock statement (Monitor.Enter/Monitor.Exit)
  • All methods on the Interlocked class
  • Asynchronous callbacks that use the thread pool — these include asynchronous delegates, APM callbacks, and Task continuations
  • Setting and waiting on a signaling construct
  • Anything that relies on signaling, such as starting or waiting on a Task

In addition, Hans Passant and Brian Gideon added the following (assuming none of which already fits into one of the previous categories):

  • Starting or waking up a thread
  • Context switch
  • Thread.Sleep()

I was wondering if this list was complete (if a complete list could even be practically made)

EDIT additions suggested:

  • Volatile (reading implies an acquire fence, writing implies a release fence)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

巴黎夜雨 2024-11-25 21:33:16

这是我对这个主题的看法,并试图在一个答案中提供一个准完整的列表。如果我遇到其他人,我会不时编辑我的答案。

人们普遍认为会导致隐式屏障的机制:

  • 所有 Monitor 类方法,包括 C# 关键字 lock
  • 所有 Interlocked 类方法。
  • 所有 Volatile 类方法 (.NET 4.5+)。
  • 大多数 SpinLock 方法包括 EnterExit
  • Thread.Join
  • Thread.VolatileReadThread.VolatileWrite
  • Thread.MemoryBarrier
  • 易失性关键词。
  • 启动线程或导致委托在另一个线程上执行的任何内容,包括 QueueUserWorkItem 、Task.Factory.StartNew 、Thread.Start 、编译器提供的BeginInvoke 方法等。
  • 使用信号机制,例如 ManualResetEventAutoResetEventCountdownEventSemaphoreBarrier 等。
  • 使用 Control.InvokeDispatcher.Invoke等封送操作SynchronizationContext.Post 等。

推测(但不确定)导致隐式障碍的机制:

  • Thread.Sleep (由我自己和可能其他人提出,因为代码表现出内存屏障问题可以用此方法修复)
  • Thread.Yield
  • Thread.SpinWait
  • Lazy 取决于哪个 LazyThreadSafetyMode指定了

其他值得注意的提及:

  • C# 中事件的默认添加和删除处理程序,因为它们使用 lockInterlocked.CompareExchange
  • x86 存储具有释放栅栏语义
  • Microsoft 的 CLI 实现在写入时具有释放栅栏语义,尽管 ECMA 规范并未强制要求这样做。
  • MarshalByRefObject 似乎抑制了子类中的某些优化,这可能使其看起来好像存在隐式内存屏障。感谢 Hans Passant 发现了这一点并引起我的注意。1

1 这解释了为什么 BackgroundWorker 可以在 CancellationPending 属性的基础字段上没有 易失性 的情况下正常工作。

Here is my take on the subject and to attempt to provide a quasi-complete list in one answer. If I run across any others I will edit my answer from time to time.

Mechanisms that are generally agreed upon to cause implicit barriers:

  • All Monitor class methods including the C# keyword lock
  • All Interlocked class methods.
  • All Volatile class methods (.NET 4.5+).
  • Most SpinLock methods including Enter and Exit.
  • Thread.Join
  • Thread.VolatileRead and Thread.VolatileWrite
  • Thread.MemoryBarrier
  • The volatile keyword.
  • Anything that starts a thread or causes a delegate to execute on another thread including QueueUserWorkItem, Task.Factory.StartNew, Thread.Start, compiler supplied BeginInvoke methods, etc.
  • Using a signaling mechanism such as ManualResetEvent, AutoResetEvent, CountdownEvent, Semaphore, Barrier, etc.
  • Using marshaling operations such as Control.Invoke, Dispatcher.Invoke, SynchronizationContext.Post, etc.

Mechanisms that are speculated (but not known for certain) to cause implicit barriers:

  • Thread.Sleep (proposed by myself and possibly others due to the fact that code which exhibits a memory barrier problem can be fixed with this method)
  • Thread.Yield
  • Thread.SpinWait
  • Lazy<T> depending on which LazyThreadSafetyMode is specified

Other notable mentions:

  • Default add and remove handlers for events in C# since they use lock or Interlocked.CompareExchange.
  • x86 stores have release fence semantics
  • Microsoft's implemenation of the CLI has release fence semantics on writes despite the fact that the ECMA specification does not mandate it.
  • MarshalByRefObject seems to suppress certain optimizations in subclasses which may make it appear as if an implicit memory barrier were present. Thanks to Hans Passant for discovering this and bringing it to my attention.1

1This explains why BackgroundWorker works correctly without having volatile on the underlying field for the CancellationPending property.

静谧 2024-11-25 21:33:16

我似乎记得 Thread.VolatileRead 和 Thread.VolatileWrite 方法的实现实际上会导致完整的栅栏,而不是半栅栏。

这是非常不幸的,因为人们可能会在不知不觉中依赖这种行为;他们可能编写了一个需要完整栅栏的程序,认为他们需要半栅栏,认为他们得到了半栅栏,并且如果这些方法的实现确实提供了半栅栏,将会感到非常惊讶。

我会避免这些方法。当然,我会避免所有涉及低锁代码的事情,除了最琐碎的情况之外,我不够聪明,无法正确编写代码。

I seem to recall that the implementations of the Thread.VolatileRead and Thread.VolatileWrite methods actually cause full fences, not half fences.

This is deeply unfortunate, as people might have come to rely upon this behaviour unknowingly; they might have written a program that requires a full fence, think they need a half fence, think they are getting a half fence, and will be in for a nasty surprise if an implementation of these methods ever does provide a half fence.

I would avoid these methods. Of course, I would avoid everything involving low-lock code, not being smart enough to write it correctly in anything but the most trivial cases.

一个人练习一个人 2024-11-25 21:33:16

volatile 关键字也充当内存屏障。请参阅 http://blogs.msdn.com/b/布拉达/archive/2004/05/12/130935.aspx

The volatile keyword acts as a memory barrier too. See http://blogs.msdn.com/b/brada/archive/2004/05/12/130935.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文