编译器在优化代码时可能会重排代码,包括存储操作的顺序。如果存储重排在条件语句之前,可能会导致程序逻辑错误。解决方法是使用内存屏障(memory barrier)或者内存栅栏(memory fence)来限制编译器的重排操作。例如,在C++代码中可以使用std::atomic_thread_fence函数在存储操作之后加上内存栅栏,来确保存储操作在条件语句之前执行,避免重排:
std::atomic flag(0);
int data = 0;
void thread1() {
data = 42;
flag.store(1, std::memory_order_release);
}
void thread2() {
while (flag.load(std::memory_order_acquire) == 0);
assert(data == 42);
}
在上述代码中,线程1先修改data的值为42并将标志位flag设为1,同时使用std::memory_order_release确保存储操作在之后的内存栅栏之前执行。线程2在循环中不断查询标志位,在std::memory_order_acquire下将保证在读取标志位后读取data时,data已经被线程1成功修改。