InterlockedExchange和内存可见性

Ser*_*kov 8 c++ windows winapi atomic interlocked

我已阅读文章同步和多处理器问题,我有一个关于InterlockedCompareExchange和InterlockedExchange的问题.问题实际上是文章中的最后一个例子.它们有两个变量iValue,fValueHasBeenComputed并且在CacheComputedValue()它们中使用InterlockedExchange以下方法修改它们:

InterlockedExchange ((LONG*)&iValue, (LONG)ComputeValue());  // don't understand
InterlockedExchange ((LONG*)&fValueHasBeenComputed, TRUE); // understand
Run Code Online (Sandbox Code Playgroud)

我知道我可以InterlockedExchange用来修改,iValue但它应该只是做

iValue = ComputeValue();
Run Code Online (Sandbox Code Playgroud)

那么实际上是否需要使用InterlockedExchange来设置iValue?或者其他线程即使正确也会看到iValue iValue = ComputeValue();.我的意思是其他线程会正确地看到iValue,因为它InterlockedExchange在它之后.

还有针对Microsoft本机代码平台的基于原理的顺序内存模型.有3.1.1示例或多或少相同的代码.其中一个推荐Make y interlocked.请注意-不能同时yx.

更新
只是为了澄清这个问题.问题是我看到了一个矛盾."同步和多处理器问题"中的示例使用两个InterlockedExchange.相反,在示例3.1.1"Basic Reodering"(我认为与第一个示例非常相似)中,Herb Sutter给出了这个推荐

"使y互锁:如果y是互锁的,那么y上没有竞赛,因为它是原子可更新的,并且x上没有竞赛,因为a - > b - > d."

.在这个草案草案中不要使用两个互锁变量(如果我是对的,他的意思是InterlockedExchange仅用于y).

Ole*_*leg 0

您只需使用 即可获得原子操作InterlockedExchange。为什么需要它?原因InterlockedExchange有两件事。

  1. 替换变量的值
  2. 返回旧值

如果您在两个操作中执行相同的操作(因此首先检查值然后替换),如果这两个操作之间出现其他指令(在另一个线程上),您可能会陷入困境。

并且您还可以防止该值上的数据争用。在这里你可以很好地解释为什么 LONG 上的读/写不是原子的

  • @jalf:我完全不同意。除非您正在编写设备驱动程序,否则您不应该对硬件做出太多假设,并且您当然不应该依赖于一整套假设,这些假设对于其他平台、编译器、数据项大小可能正确也可能不正确,或操作系统。在多线程应用程序中,对需要原子性的共享对象的操作需要来自操作系统或编译器的互斥保护。依赖硬件的怪癖是非常糟糕的做法。 (2认同)