我正在研究编译器优化(特别是这里的指令重新排序)可能对多线程程序产生的影响。
假设我们有一个读者线程和一个写作者线程。
// Global shared data between threads
bool data;
bool flag = false;
// writer.cpp
void writer()
{
data = true; // (1)
flag = true; // (2)
}
// reader.cpp
void reader()
{
if (flag)
{
count << data;
}
}
是否符合C ++ 11标准的编译器重新排序指令(1)
和(2)
?
根据C ++“as-if”规则,转换不应该改变程序的可观察行为。显然,在编译编写器时,编译器通常无法确定重新排序(1)
和(2)
是否会改变程序的可观察行为,因为data
和flag
是两个全局变量都可能影响另一个线程的可观察行为。
但它在此声明可以发生这种重新排序,请参阅memory ordering at compile time。
那么我们需要(1)
和(2)
之间的编译屏障吗? (我很清楚可能的CPU重新排序。这个问题仅适用于编译器重新排序)
答案 0 :(得分:5)
绝对可能。编译器没有义务考虑对其他线程或硬件的副作用。
如果您使用volatile
或同步(并且这两个不可互换),编译器只会被考虑这一点。
标准内存模型称为SC-DRF,或顺序一致数据竞争免费。数据竞争正是您刚刚描述的情景 - 一个线程正在观察非同步变量而另一个正在变异。这是未定义的行为。实际上,标准明确地赋予编译器自由,假设没有其他线程或硬件正在读取非易失性非同步变量。编译器在此基础上进行优化是绝对合法的。
顺便说一句,那个链接有点废话。他的修复&#34;根本不解决任何问题。多线程代码唯一正确的解决方法是使用同步。
答案 1 :(得分:2)
你已经在一周半之前就comp.lang.c ++。问了这个问题,你得到了关于C ++ 11在单个线程中排序的要求与“for”之间关系的完整解释。发生在“线程之间的同步关系之前,这里:https://groups.google.com/forum/#!topic/comp.lang.c++.moderated/43_laZwVXYg
您不了解该回复的哪一部分,我们可以再试一次?