代码之家  ›  专栏  ›  技术社区  ›  Bill W

使用什么而不是互锁。等于

  •  3
  • Bill W  · 技术社区  · 16 年前

    我有一些使用interlocked.equals比较值的遗留代码。值可以是两个布尔值,也可以将一个结构数组与空值进行比较。resharper抱怨interlocked.equals说“通过派生类型访问类型的静态成员”。我知道equals不是联锁类的成员,而是对象类的成员。比较发生在一个线程中,因此我假设原始的编码人员希望将比较作为一个原子操作来进行,因此使用了互锁。既然object.equals不是原子的,那么进行这些比较的正确的、线程安全的方法是什么? 注意,大多数数据是静态的,其中一些数据是静态的易失性的。

    2 回复  |  直到 16 年前
        1
  •  5
  •   Stephen Cleary    16 年前

    布尔值或对象引用的单个读取是原子的。所以,如果将一个共享值与一个常量或局部变量进行比较,就不需要“互锁”。如乔恩所说,你需要 Interlocked.CompareExchange 除非共享变量 volatile .

    如果两个比较数是共享的,那么您将需要一个实际的锁。没有一种方法可以原子地比较两个共享值。

    更新:

    我确实建议为共享数据引入显式锁。请记住,原始代码完全被破坏了,所以不要羞于更改它。

    如果你考虑一下,你会对比较的结果做些什么?这真的没有意义;一旦你得到结果,它可能是错误的。一个锁需要保持更长的时间,而不仅仅是为了比较,以便比较对任何事情都有用。

        2
  •  6
  •   Jon Skeet    16 年前

    你不能让整个比较成为原子性的,但它不是你真正感兴趣的原子性。我怀疑这是波动性。这就是当你读到一个值时,你肯定会得到最新的版本,而不是看到一个值 是 在过去的某个时候有效,但可能不是。如果你 真正地 需要整个读/读/比较部分的原子性,我怀疑您需要锁定。

    你可以使用 Interlocked.CompareExchange 以确保您正在读取最新的值。

    您是否必须首先使用无锁线程?我强烈建议要么建立在更大的结构之上(例如并行扩展),要么仅仅使用共享数据的锁(在可能的情况下应该尽量避免)。

    推荐文章