(这是以下内容的重复:如何正确读取Interlocked.Increment'ed int字段?但是,在阅读了答案和评论之后,我仍然不确定正确的答案。)
我不拥有一些代码,不能更改为使用在多个不同线程中增加int计数器(numberOfUpdates)的锁的代码。所有通话都使用:
Interlocked.Increment(ref numberOfUpdates);
我想在代码中阅读numberOfUpdates。现在,由于这是一个整数,所以我知道它不会撕裂。但是,确保我能获得最新价值的最佳方法是什么?看来我的选择是:
int localNumberOfUpdates = Interlocked.CompareExchange(ref numberOfUpdates, 0, 0);
要么
int localNumberOfUpdates = Thread.VolatileRead(numberOfUpdates);
两者都可以工作(在不考虑优化,重新排序,缓存等的情况下,尽可能提供最新的价值)吗?一个比另一个更好吗?还有第三种更好的选择吗?
我坚信如果您使用互锁来增加共享数据,那么在访问共享数据的任何地方都应该使用互锁。同样,如果在此处使用“插入您喜欢的同步原语”来增加共享数据,那么在访问共享数据的任何地方都应在此处使用“插入您喜欢的同步原语”。
int localNumberOfUpdates = Interlocked.CompareExchange(ref numberOfUpdates, 0, 0);
会给您您想要的东西。正如其他人所说,互锁操作是原子的。因此,Interlocked.CompareExchange将始终返回最新值。我一直在使用它来访问简单的共享数据(例如计数器)。
我对Thread.VolatileRead不太熟悉,但我怀疑它还会返回最新值。如果只是为了保持一致,我会坚持使用互锁的方法。
附加信息:
我建议您看一下乔恩·斯基特(Jon Skeet)的答案,为什么您可能想回避Thread.VolatileRead():Thread.VolatileRead实现
埃里克·利珀特(Eric Lippert)在其博客(http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different)中讨论了波动性和C#内存模型所提供的保证。-part-three.aspx。直截了当:“除互锁操作的最简单用法外,我不尝试编写任何低锁代码。我将“ volatile”的用法留给真正的专家使用。”
我同意Hans的观点,即该值至少会过时数ns,但是如果您有一个用例不可接受,那么它可能不太适合像C#或非真实的垃圾收集语言时间操作系统。Joe Duffy在这里有一篇很好的文章,介绍了互锁方法的及时性:http : //joeduffyblog.com/2008/06/13/volatile-reads-and-writes-and-timeliness/
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句