繁体   English   中英

联锁和不稳定

[英]Interlocked and volatile

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

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

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

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

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

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

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM