阅读Joseph Albahari's threading tutorial,以下内容被提及为内存障碍的生成器:
lock
声明(Monitor.Enter
/ Monitor.Exit
)Interlocked
类此外,Hans Passant和Brian Gideon added the following(假设其中任何一个都不适合以前的类别之一):
Thread.Sleep()
我想知道这个清单是否完整(如果完整清单甚至可以实现)
建议添加编辑:
答案 0 :(得分:32)
这是我对这个主题的看法,并尝试在一个答案中提供一个准完整列表。如果我碰到其他人,我会不时编辑我的答案。
通常商定的导致隐含障碍的机制:
Monitor
类方法,包括C#关键字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
。MarshalByRefObject
似乎抑制了子类中的某些优化,这可能使其看起来好像存在隐式内存屏障。感谢Hans Passant发现这一点并引起我的注意。 1 1 这解释了BackgroundWorker
在volatile
属性的基础字段上没有CancellationPending
的情况下正常工作的原因。
答案 1 :(得分:11)
我似乎记得Thread.VolatileRead和Thread.VolatileWrite方法的实现实际上会导致完整的栅栏,而不是半栅栏。
这是非常不幸的,因为人们可能在不知不觉中开始依赖这种行为;他们可能已经编写了一个需要完整围栏的程序,认为他们需要一个半围栏,认为他们正在获得一个半围栏,并且如果这些方法的实现确实提供了一个半围栏,那将会产生令人讨厌的惊喜。
我会避免这些方法。当然,我会避免涉及低锁代码的所有内容,除了最琐碎的案例之外,还不够聪明,不能正确地编写代码。
答案 2 :(得分:3)
volatile
关键字也充当了内存屏障。见http://blogs.msdn.com/b/brada/archive/2004/05/12/130935.aspx