您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

引用分配是原子的,那么为什么需要Interlocked.Exchange(ref Object,Object)?

引用分配是原子的,那么为什么需要Interlocked.Exchange(ref Object,Object)?

这里有很多问题。一次考虑一个

引用分配是原子的,那么为什么需要Interlocked.Exchange(ref Object,Object)?

参考分配是原子的。Interlocked.Exchange不只引用分配。它会读取变量的当前值,将旧值存储起来,并将新值分配给变量,所有这些操作都是原子操作。

我的同事说,在某些平台上,不能保证引用分配是原子的。我的同事正确吗?

不能。在所有.NET平台上,引用分配都是原子的。

我的同事是从错误的前提进行推理。这是否意味着他们的结论不正确?

不必要。您的同事出于不好的原因可能会给您很好的建议。也许还有其他原因使您应该使用Interlocked.Exchange。无锁编程非常困难,一旦您偏离了该领域专家公认的成熟实践,您就会陷入困境,并冒着最恶劣的比赛条件的危险。我既不是该领域的专家,也不是您的代码的专家,所以我无法做出一种判断。

产生警告“对volatile字段的引用将不会被视为volatile”我应该怎么看?

您应该了解为什么这通常是一个问题。这将导致理解为什么在此特定情况下警告不重要。

编译器发出此警告的原因是,将字段标记为volatile意味着“该字段将在多个线程上进行更新- 不会生成任何缓存该字段值的代码,并确保对该字段的任何读或写该字段不会通过处理器缓存不一致而“在时间上向前和向后移动”。

(我假设您已经了解了所有内容。如果您对volatile的含义及其对处理器缓存语义的影响没有详细的了解,那么您将不了解它的工作原理,并且不应该使用volatile。无锁程序很难做到正确;请确保您的程序是正确的,因为您了解程序的工作原理,而不是偶然的结果。)

现在假设您通过将ref传递给该字段来创建一个变量,该变量是volatile字段的别名。在被调用方法内部,编译器没有任何理由知道引用需要具有易变的语义!编译器会为无法实现易失字段规则的方法高兴地生成代码,但是变量 易失字段。那会完全破坏您的无锁逻辑。始终假设总是使用易失性语义 访问易失性字段。有时(而不是其他时间)将其视为不稳定是没有意义的;您必须始终 保持一致,否则您不能保证其他访问的一致性。

因此,编译器在执行此操作时会发出警告,因为它可能会完全破坏您精心开发的无锁逻辑。

当然,Interlocked.Exchange 编写 为了期待一个易变的字段并做正确的事。因此,该警告具有误导性。我对此感到非常遗憾。我们应该做的是实现一种机制,通过这种机制,像Interlocked.Exchange这样的方法的作者可以在该方法添加一个属性,说“该方法使用ref会对变量施加易变义的语义,从而消除警告”。也许在将来的编译器版本中,我们会这样做。

其他 2022/1/1 18:16:12 有424人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶