Interlocked是否保证C#中其他线程的可见性,还是仍然需要使用volatile?

我一直在阅读类似问题的答案,但我仍然有点困惑……亚伯有一个很好的答案,但这是我不确定的部分:

…声明变量volatile会使每次访问都变得不稳定。 不可能以任何其他方式强制执行此行为,因此不能用Interlocked替换volatile。 在其他库,接口或硬件可以访问您的变量并随时更新它或需要最新版本的情况下,这是必需的。

Interlocked是否保证对所有线程的primefaces操作的可见性,或者我是否仍然必须在值上使用volatile关键字以保证对更改的可见性?

这是我的例子:

 volatile int value = 100000; // 0) { // do something } } public void AThreadMethod() { while(value > 0) { // do something } } 

更新:
我是一个糟糕的运动,我改变了原来的例子,所以这里又是:

 public class CountDownLatch { private volatile int m_remain; // <--- do I need the volatile keyword here? private EventWaitHandle m_event; public CountDownLatch(int count) { Reset(count); } public void Reset(int count) { if (count < 0) throw new ArgumentOutOfRangeException(); m_remain = count; m_event = new ManualResetEvent(false); if (m_remain == 0) { m_event.Set(); } } public void Signal() { // The last thread to signal also sets the event. if (Interlocked.Decrement(ref m_remain) == 0) m_event.Set(); } public void Wait() { m_event.WaitOne(); } } 

他们不需要**波动率,因为你从不检查互锁变量的值。 相反,您始终检查互锁操作返回的值。 混合互锁操作和普通分配/比较总是导致错误的代码。

我不确定Reset()函数的意图是什么,但是这段代码在线程间原语中没有位置:你分配给m_remain,你直接检查m_remain的值,非常糟糕。 我强烈建议你把它拿出来:不仅实现不正确,而且我非常怀疑需要“重置”计数器中期寿命的语义。 保持简单:ctor(将代码从Reset移动到其中)Signal和Wait是唯一需要的三个运算符,它们现在是正确的。

更新编辑代码后。

忽略你不应该混合两者的事实,如果你最终混合它们然后是,仍然需要挥发性。 易失性主要是关于IL代码和生成的JIT代码,以确保始终从实际内存位置读取值,并且不进行优化,例如代码重新排序。 不相关的代码片段使用Interlocked操作更新值的事实对读取该值的其他部分没有影响。 如果没有volatile属性,编译器/ JIT仍然可能生成忽略其他地方发生的写入的代码,如果写入是互锁或直接赋值则无关紧要。

顺便说一句,有一些有效的模式混合普通的读取和互锁操作,但它们通常涉及Interlocked.CompareExchange,并且这样:go当前状态,根据当前状态进行一些计算,尝试将状态替换为互锁比较交换:如果成功,如果没有删除计算结果并返回步骤1。

我认为System.Threading.Thread.VolatileRead(ref myVariable)可能就是你要找的东西。 与Interlocked.Increment结合使用,它可用于保证更改是primefaces的,并且您读取的值是最新的。