这里有很多问题。一次考虑一个:
引用分配是原子的,那么为什么需要Interlocked.Exchange(ref Object,Object)?
参考分配是原子的。Interlocked.Exchange不只引用分配。它会读取变量的当前值,将旧值存储起来,并将新值分配给变量,所有这些 *** 作都是原子 *** 作。
我的同事说,在某些平台上,不能保证引用分配是原子的。我的同事正确吗?
不能。在所有.NET平台上,引用分配都是原子的。
我的同事是从错误的前提进行推理。这是否意味着他们的结论不正确?
不必要。您的同事出于不好的原因可能会给您很好的建议。也许还有其他原因使您应该使用Interlocked.Exchange。无锁编程非常困难,一旦您偏离了该领域专家公认的成熟实践,您就会陷入困境,并冒着最恶劣的比赛条件的危险。我既不是该领域的专家,也不是您的代码的专家,所以我无法做出一种判断。
产生警告“对volatile字段的引用将不会被视为volatile”我应该怎么看?
您应该了解为什么这通常是一个问题。这将导致理解为什么在此特定情况下警告不重要。
编译器发出此警告的原因是,将字段标记为volatile意味着“该字段将在多个线程上进行更新-
不会生成任何缓存该字段值的代码,并确保对该字段的任何读或写该字段不会通过处理器缓存不一致而“在时间上向前和向后移动”。
(我假设您已经了解了所有内容。如果您对volatile的含义及其对处理器缓存语义的影响没有详细的了解,那么您将不了解它的工作原理,并且不应该使用volatile。无锁程序很难做到正确;请确保您的程序是正确的,因为您了解程序的工作原理,而不是偶然的结果。)
现在假设您通过将ref传递给该字段来创建一个变量,该变量是volatile字段的别名。在被调用的方法内部,编译器没有任何理由知道引用需要具有易变的语义!编译器会为无法实现易失字段规则的方法高兴地生成代码,但是变量
是 易失字段。那会完全破坏您的无锁逻辑。始终假设总是使用易失性语义 来 访问易失性字段。有时(而不是其他时间)将其视为不稳定是没有意义的;您必须
始终 保持一致,否则您不能保证其他访问的一致性。
因此,编译器在执行此 *** 作时会发出警告,因为它可能会完全破坏您精心开发的无锁逻辑。
当然,Interlocked.Exchange 的 编写 是
为了期待一个易变的字段并做正确的事。因此,该警告具有误导性。我对此感到非常遗憾。我们应该做的是实现一种机制,通过这种机制,像Interlocked.Exchange这样的方法的作者可以在该方法上添加一个属性,说“该方法使用ref会对变量施加易变义的语义,从而消除警告”。也许在将来的编译器版本中,我们会这样做。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)