#include <iostream>
#include <thread>
#include <mutex>
int main()
{
std::atomic<bool> ready = false;
std::thread threadB = std::thread([&]() {
while (!ready) {}
printf("Hello from B\n");
});
std::this_thread::sleep_for(std::chrono::seconds(1));
printf("Hello from A\n");
ready = true;
threadB.join();
printf("Hello again from A\n");
}
这是来自CppCon演讲https://www.youtube.com/watch?v=F6Ipn7gCOsY&ab_channel=CppCon的一个例子(17分钟)。
目标是先打印Hello from A
,然后允许threadB
启动。很明显,应该避免繁忙等待,因为它会使用大量CPU。
作者说while (!ready) {}
循环可以被编译器优化(通过将ready
的值放入寄存器),因为编译器看到threadB
从不休眠,所以ready
永远不会改变。但即使线程从不休眠,其他线程仍然可以更改该值,对吗?由于ready
是原子的,因此不存在数据竞争。作者指出这段代码是UB。有人能解释一下为什么编译器允许这样的优化吗?
std::atomic
的整个意义在于它实际上可以突然改变,编译器不能做其他假设。去除这个循环将非常改变程序的可观察行为,因此不是一个有效的优化。 - Igor Tandetnikready.load()
。 - Igor Tandetnik