为什么启用优化后代码片段会卡住?
Why the code snippet gets stuck when optimization is enabled?
下面的代码片段有3个问题。
- 当宏(即
NO_STUCK_WITH_OPTIMIZATION
)未启用时,为什么this code snippet在启用优化(即-O1
、-O2
或[=14时卡住=]) 而如果未启用优化,程序运行良好?
- 为什么加了
std::this_thread::sleep_for()
程序就不会卡了?
已更新:
3、如果is_run
声明为volatile
(详见the code snippet), then the program would never get stuck on X86?
^^更新结束^^
#include <functional>
#include <thread>
#include <iostream>
#include <chrono>
#include <atomic>
#ifdef NO_STUCK_WITH_OPTIMIZATION
using TYPE = std::atomic<int>;
#else
using TYPE = int; //The progrom gets stuck if the optimization is enabled.
#endif
int main()
{
TYPE is_run{1};
auto thread = std::thread([&is_run](){while(1==is_run){
//std::this_thread::sleep_for(std::chrono::milliseconds(10)); //If this line is added, the program is no longer gets stuck. Why?
}
std::cout << "thread game over" << std::endl;
});
std::this_thread::sleep_for(std::chrono::seconds(1));
is_run = 0;
thread.join();
}
您有一个 multi-threaded 程序。一个线程执行 is_run = 0;
.
另一个线程执行 while(1==is_run)
。虽然你保证睡眠(另一个问题),写在读之前完成,你需要告诉编译器同步这个变量。
在 C++ 中,确保一个线程看到更改的简单方法是使用 atomic<int>
。如果您不这样做,其他线程可能永远看不到更改。这种更改的隐藏可能是由于编译时代码的局部优化,OS 决定不刷新某些内存页面或硬件本身决定不需要重新加载内存。
放置原子变量可以保证所有这些系统都知道你想做什么。所以,使用它。 :-)
摘自评论:
https://en.cppreference.com/w/cpp/language/memory_model#Threads_and_data_races
A program that has two conflicting evaluations has a data race unless both evaluations execute on the same thread or in the same signal handler, or
both conflicting evaluations are atomic operations (see std::atomic), or one of the conflicting evaluations happens-before another (see std::memory_order) If a data race occurs, the behavior of the program is undefined.
下面的代码片段有3个问题。
- 当宏(即
NO_STUCK_WITH_OPTIMIZATION
)未启用时,为什么this code snippet在启用优化(即-O1
、-O2
或[=14时卡住=]) 而如果未启用优化,程序运行良好? - 为什么加了
std::this_thread::sleep_for()
程序就不会卡了?
已更新:
3、如果is_run
声明为volatile
(详见the code snippet), then the program would never get stuck on X86?
^^更新结束^^
#include <functional>
#include <thread>
#include <iostream>
#include <chrono>
#include <atomic>
#ifdef NO_STUCK_WITH_OPTIMIZATION
using TYPE = std::atomic<int>;
#else
using TYPE = int; //The progrom gets stuck if the optimization is enabled.
#endif
int main()
{
TYPE is_run{1};
auto thread = std::thread([&is_run](){while(1==is_run){
//std::this_thread::sleep_for(std::chrono::milliseconds(10)); //If this line is added, the program is no longer gets stuck. Why?
}
std::cout << "thread game over" << std::endl;
});
std::this_thread::sleep_for(std::chrono::seconds(1));
is_run = 0;
thread.join();
}
您有一个 multi-threaded 程序。一个线程执行 is_run = 0;
.
另一个线程执行 while(1==is_run)
。虽然你保证睡眠(另一个问题),写在读之前完成,你需要告诉编译器同步这个变量。
在 C++ 中,确保一个线程看到更改的简单方法是使用 atomic<int>
。如果您不这样做,其他线程可能永远看不到更改。这种更改的隐藏可能是由于编译时代码的局部优化,OS 决定不刷新某些内存页面或硬件本身决定不需要重新加载内存。
放置原子变量可以保证所有这些系统都知道你想做什么。所以,使用它。 :-)
摘自评论:
https://en.cppreference.com/w/cpp/language/memory_model#Threads_and_data_races
A program that has two conflicting evaluations has a data race unless both evaluations execute on the same thread or in the same signal handler, or both conflicting evaluations are atomic operations (see std::atomic), or one of the conflicting evaluations happens-before another (see std::memory_order) If a data race occurs, the behavior of the program is undefined.