我知道 volatile
通知编译器值可能会改变,但是为了实现这个功能,编译器是否需要引入一个内存栅栏来使其工作?
根据我的理解,对易失性对象的操作序列不能被重新排序,必须被保留。这似乎意味着一些内存栅栏是必要的,并且没有真正的办法绕过这一点。我说的对吗?
在 这个相关的问题有一个有趣的讨论
... 对不同的可变变量的访问不能由 编译器,只要它们出现在单独的完整表达式... 对 易失性对于线程安全是无用的,但不是因为他 这并不是因为编译器可能重新排序访问 而是因为 CPU 可能会对它们重新排序 操作和内存屏障阻止编译器和 CPU 重新排序
David Schwartz对此答复 在评论中:
没有区别,从 C + + 标准的角度来看, 在编译器做某事和编译器发出 指令,导致硬件做一些事情。如果中央处理器可以 重新排序对挥发物的访问,那么标准就不需要这个了 他们的秩序得以维持。
... C + + 标准并没有区分 重新排序。而且你不能争辩说,CPU 可以重新排序他们没有 可观察到的效果,所以没关系 C + + 标准定义了它们的 编译器符合 C + + 标准 一个平台,如果它生成代码,使平台做什么 标准要求。如果标准要求访问挥发物 被重新排序,然后一个平台重新排序他们是不符合..。
我的观点是,如果 C + + 标准禁止编译器 对不同的挥发物进行重新排序的理论是 这种访问的顺序是程序可观察行为的一部分, 那么它也要求编译器发出代码,禁止 CPU 标准并没有区分 编译器做什么和编译器的生成代码使 CPU 做什么。
这就产生了两个问题: 它们中的任何一个是“正确的”吗? 实际的实现到底是做什么的?