我有一个变量,我用来表示状态.它可以从多个线程读取和写入.
我正在使用Interlocked.Exchange
并Interlocked.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
jer*_*jvl 41
互锁操作和易失性并不是真的应该同时使用.你得到警告的原因是因为它(几乎?)总是表明你误解了你在做什么.
过度简化和释义:
volatile
表示每次读取操作都需要从内存中重新读取,因为可能有其他线程更新变量.当应用于可以由您运行的体系结构以原子方式读/写的字段时,除非您使用long/ulong,否则这应该是您需要做的所有事情,大多数其他类型可以原子方式读/写.
当字段没有标记为volatile时,您可以使用Interlocked
操作来进行类似的保证,因为它会刷新缓存,以便所有其他处理器都可以看到更新...这样可以节省开销更新而不是读取.
这两种方法中哪一项表现最佳取决于您究竟在做什么.这种解释过于简单化.但是应该从中可以清楚地看出,同时做这两件事是毫无意义的.
归档时间: |
|
查看次数: |
12637 次 |
最近记录: |