联锁和不稳定

tra*_*ter 70 .net c# mono

我有一个变量,我用来表示状态.它可以从多个线程读取和写入.

我正在使用Interlocked.ExchangeInterlocked.CompareExchange改变它.但是我从多个线程中读取它.

我知道volatile可以用来确保变量不在本地缓存,但总是直接从内存中读取.

但是,如果我将变量设置为volatile,则会生成有关使用volatile并使用ref传递给Interlocked方法的警告.

我想确保每个线程都读取变量的最新值而不是某些缓存版本,但我不能使用volatile.

有一个Interlocked.Read 但是它适用于64位类型,并且在紧凑的框架上不可用.它的文档说32位类型不需要它,因为它们已经在一次操作中执行.

如果您使用Interlocked方法进行所有访问,则互联网上有一些声明您不需要使用volatile.但是,您无法使用Interlocked方法读取32位变量,因此您无法使用Interlocked方法进行所有访问.

有没有办法在不使用锁的情况下完成我的变量的线程安全读写?

Ant*_*hyy 42

在使用Interlocked.Xxx函数时可以放心地忽略该警告(请参阅此问题),因为它们总是执行不稳定操作.因此,volatile对于共享状态,变量是完全正常的.如果你想不惜一切代价摆脱警告,你实际上可以做一个互锁的阅读Interlocked.CompareExchange (ref counter, 0, 0).

编辑:实际上,只有当你要直接写入它(即不使用)时,你才需要volatile你的状态变量.正如jerryjvl所提到的,读取使用互锁(或易失性)操作更新的变量将使用最新值.Interlocked.Xxx

  • Phew,如果没有,Interlocked将毫无用处.在那里吓到我一分钟:) (3认同)
  • 对非“易失性”变量的读取是否被编译器或 JIT 优化掉了?引用@jerryjvl 的编辑是不是不正确? (2认同)

jer*_*jvl 41

互锁操作和易失性并不是真的应该同时使用.你得到警告的原因是因为它(几乎?)总是表明你误解了你在做什么.

过度简化和释义:
volatile表示每次读取操作都需要从内存中重新读取,因为可能有其他线程更新变量.当应用于可以由您运行的体系结构以原子方式读/写的字段时,除非您使用long/ulong,否则这应该是您需要做的所有事情,大多数其他类型可以原子方式读/写.

当字段没有标记为volatile时,您可以使用Interlocked操作来进行类似的保证,因为它会刷新缓存,以便所有其他处理器都可以看到更新...这样可以节省开销更新而不是读取.

这两种方法中哪一项表现最佳取决于您究竟在做什么.这种解释过于简单化.但是应该从中可以清楚地看出,同时做这两件事是毫无意义的.

  • Joe Duffy在[本博客文章]中特别谈到了对volatile/Interlocked操作的引用(http://www.bluebytesoftware.com/blog/CommentView,guid,c36d1633-50ab-4462-993e-f1902f8938cc.aspx).与引用互锁的混合是100%好的,并且他请求在C#编译器中添加一个特殊情况,在这种情况下不要发出警告. (9认同)
  • 当前链接到 Joe duffy 博客在它的新家 http://joeduffyblog.com/2008/06/13/volatile-reads-and-writes-and-timeliness/ http://joeduffyblog.com/2009/02/02 /c-compiler-warning-cs0420-byrefs-to-volatiles/ http://joeduffyblog.com/2007/11/10/clr-20-memory-model/ (4认同)
  • 使用volatile和Interlocked并没有什么本质上的错误.你会得到一个警告的原因是`volatile`是`volatile`不是类型系统的一部分,谁接收参考不知道所引用的变量需要挥发性访问被调用者. (2认同)
  • 为了记录,有[这里的讨论](http://stackoverflow.com/questions/6139699/how-to-correctly-read-an-interlocked-incremented-int-field),其中建议这个答案是错误的.@jerryjvl,如果你想贡献那将是伟大的. (2认同)
  • 这比我第一次写这个答案时所意识到的更为微妙.我强烈建议阅读Joe Duffy(和/或他的并发书),以便在解决问题的背景下详细了解.在谈到这些问题时,他真的是权威.无锁的一个大问题是它通常是关于某种意义上的性能,但是在这种方式中存在一些缺陷,可能产生不正确的结果或降低所寻求的性能. (2认同)