InterlockedExchange 和内存可见性
我已阅读文章同步和多处理器问题 我有一个关于 InterlockedCompareExchange 和 InterlockedExchange 的问题。问题实际上是关于文章中的最后一个例子。他们有两个变量iValue
和fValueHasBeenCompulated
,在CacheCompulatedValue()
中,他们使用InterlockedExchange
修改它们中的每一个:
InterlockedExchange ((LONG*)&iValue, (LONG)ComputeValue()); // don't understand
InterlockedExchange ((LONG*)&fValueHasBeenComputed, TRUE); // understand
我明白我可以使用 InterlockedExchange 来修改 iValue 但仅仅这样做就足够了
iValue = ComputeValue();
那么实际上有必要使用 InterlockedExchange 来设置 iValue 吗?或者即使iValue = ComputeValue();
,其他线程也会正确地看到iValue。我的意思是其他线程将正确地看到 iValue,因为它后面有 InterlockedExchange。
还有论文基于原理的顺序内存Microsoft 本机代码平台模型。 3.1.1 示例的代码大致相同。建议之一使 y 互锁
。注意 - 不能同时使用 y
和 x
。
更新
只是为了澄清问题。问题是我看到了矛盾。 “同步和多处理器问题”中的示例使用两个 InterlockedExchange
。相反,在示例 3.1.1“Basic Reordering”(我认为与第一个示例非常相似)中,Herb Sutter 给出了这个建议
“使 y 互锁:如果 y 互锁,则 y 上不存在竞争 因为它是原子可更新的,并且 x 上没有竞争,因为 -> b-> d.”
。在此草案中,Herb 不使用两个互锁变量(如果我是对的,他的意思是仅对 y
使用 InterlockedExchange
)。
I have read the article Synchronization and Multiprocessor Issues and I have a question about InterlockedCompareExchange and InterlockedExchange. The question is actually about the last example in the article. They have two variables iValue
and fValueHasBeenComputed
and in CacheComputedValue()
they modify each of them using InterlockedExchange
:
InterlockedExchange ((LONG*)&iValue, (LONG)ComputeValue()); // don't understand
InterlockedExchange ((LONG*)&fValueHasBeenComputed, TRUE); // understand
I understand that I can use InterlockedExchange
for modifing iValue
but is it enought just to do
iValue = ComputeValue();
So is it actually necessary to use InterlockedExchange
to set iValue? Or other threads will see iValue correctly even if iValue = ComputeValue();
. I mean the other threads will see iValue correctly because there is InterlockedExchange
after it.
There is also the paper A Principle-Based Sequential Memory Model for Microsoft Native Code Platforms. There is the 3.1.1 example with more or less the same code. One of the recomendation Make y interlocked
. Notice - not both y
and x
.
Update
Just to clarify the question. The issue is that I see a contradiction. The example from "Synchronization and Multiprocessor Issues" uses two InterlockedExchange
. On the contrary, in the example 3.1.1 "Basic Reodering" (which I think is quite similar to the first example) Herb Sutter gives this recomendation
"Make y interlocked: If y is interlocked, then there is no race on y
because it is atomically updatable,and there is no race on x because a
-> b -> d."
. In this draft Herb do not use two interlocked variable (If I am right he means use InterlockedExchange
only for y
).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果 iValue 的地址未与保证原子访问的地址对齐,他们这样做是为了防止部分读/写。当两个或多个物理线程尝试同时写入值,或者一个读取且一个尝试同时写入时,就会出现此问题。
其次,应该注意的是,存储并不总是全局可见的,它们仅在通过栅栏或总线锁序列化时才可见。
They did that to prevent partial reads/writes if the address of
iValue
is not aligned to an address that guarantees atomic access. this problem would arise when two or more physical thread try to write the value concurrently, or one reads and one tries to write at the same time.As a secondary point, it should be noted that stores are not always globally visible, they are only going to be visible when serialized, either by a fence or by a bus lock.
您只需使用 InterlockedExchange 即可获得原子操作。为什么需要它?
因为
InterlockedExchange
做了两件事。如果您在两个操作中执行相同的操作(因此首先检查值然后替换),如果这两个操作之间发生其他指令(在另一个线程上),您可能会陷入困境。
而且您还可以防止数据竞争这个值。 在这里你会得到一个很好的解释为什么读/写LONG 不是原子的
You simply get an atomic operation with
InterlockedExchange
. Why you need it?Cause
InterlockedExchange
does 2 things.If you do the same things in 2 operations (Thus first check value then replace) you can get screwed if other instructions (on another thread) occur between these 2.
And you also prevent data races on this value. here you get a good explanation why read/write on a LONG is not atomic
对于您所观察到的矛盾,有两种看似合理的解决方案。
其一是第二份文件在这一特定方面完全是错误的。毕竟,它只是一个草案。我注意到您引用的示例明确指出程序员不能依赖写入是原子的,这意味着两次写入确实必须是互锁的。
另一个是,在该特定示例中实际上可能不需要额外的互锁,因为这是一种非常特殊的情况:仅更改变量的一位。然而,正在开发的规范似乎没有提到这一点作为前提,所以我怀疑这是故意的。
There are two plausible resolutions to the contradiction you've observed.
One is that the second document is simply wrong in that particular respect. It is, after all, a draft. I note that the example you refer to specifically states that the programmer cannot rely on the writes to be atomic, which means that both writes must indeed be interlocked.
The other is that the additional interlock might not actually be required in that particular example, because it is a very special case: only a single bit of the variable is being changed. However, the specification being developed doesn't appear to mention this as a premise, so I doubt that this is intentional.
我认为这个讨论已经回答了这个问题: 隐式内存屏障。
内存屏障:软件黑客的硬件视图和 Xbox 360 和 Microsoft Windows 的无锁编程注意事项也很有趣。
I think this discussion has the answer to the question: Implicit Memory Barriers.
Memory Barriers: a Hardware View for Software Hackers and Lockless Programming Considerations for Xbox 360 and Microsoft Windows are also insteresting.