联锁和不稳定

时间:2009-07-27 05:06:10

标签: c# .net mono

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

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

我知道volatile可用于确保变量不在本地缓存,但始终直接从内存中读取。

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

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

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

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

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

2 个答案:

答案 0 :(得分:37)

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

修改:实际上,如果要直接写入,则需要{i}仅的状态变量<{1}}(即不使用{{1} })。 As jerryjvl mentioned,读取使用互锁(或易失性)操作更新的变量将使用最新值。

答案 1 :(得分:37)

互锁操作和volatile实际上并不应该同时使用。你收到警告的原因是因为它(几乎?)总是表明你误解了你在做什么。

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

当字段未标记为volatile时,您可以使用Interlocked操作进行类似的保证,因为它会刷新缓存,以便所有其他处理器都可以看到更新...将开销放在更新而不是读取上的好处。

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