我有一些使用Interlocked.Equals比较值的遗留代码。值可以是两个布尔值,也可以将结构数组与null进行比较。Resharper抱怨Interlocked.Equals说“通过派生类型访问类型的静态成员”。我知道Equals不是互锁类的成员,而是object类的成员。比较是在线程中进行的,所以我假设最初的编码器希望将比较作为原子操作进行,因此使用了互锁。既然object.Equals不是原子的,那么什么才是正确的、线程安全的方式来进行这种比较呢?请注意,大部分数据是静态的,其中一些是静态易失性的。
发布于 2010-07-20 22:27:40
单次读取布尔值或对象引用是原子的。因此,如果您将一个共享值与一个常量或局部变量进行比较,则不需要“互锁”。正如Jon所说,除非共享变量为volatile,否则您需要使用Interlocked.CompareExchange来确保读取的是最新写入的值。
如果两个比较数都是共享的,那么您将需要一个实际的锁。没有办法自动比较两个共享值AFAIK。
更新:
我建议为共享数据引入显式锁。请记住,原始代码已经完全损坏了,所以不要害怕更改它。
如果你想一想,你会如何处理比较的结果?这没有什么意义;一旦你有了结果,它就可能是错误的。锁需要保持更长的时间,而不仅仅是为了进行比较,以便比较对任何事情都有用。
发布于 2010-07-20 22:28:07
你不能让整个比较都是原子的,但你真正感兴趣的不是原子性。我怀疑这是波动性。这就确保了当你读取一个值时,你肯定会得到最新的版本,而不是看到一个在过去的某个时候是有效的,但可能不是。如果您确实需要跨读/读/比较部分的原子性,我怀疑您将需要锁定。
您可以使用Interlocked.CompareExchange来确保读取的是最新的值。
你一定要在一开始就使用无锁线程吗?我强烈建议要么建立在更大的结构之上(例如并行扩展),要么只对共享数据使用锁(无论如何都应该避免这样做)。
https://stackoverflow.com/questions/3290945
复制相似问题