關于下面的代碼片段有三個問題。
- 當宏(即
NO_STUCK_WITH_OPTIMIZATION)未啟用時,為什么此代碼片段-O1在啟用優化(即,-O2或)時卡住,-O3而如果未啟用優化,程式運行良好? - 如果添加,為什么程式不再卡住
std::this_thread::sleep_for()?
更新: 3. 如果is_run宣告為volatile(有關詳細資訊,請參閱代碼片段),那么程式永遠不會卡在 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();
}
uj5u.com熱心網友回復:
你有一個多執行緒程式。一個執行緒可以is_run = 0;。
另一個執行緒可以while(1==is_run)。盡管您通過睡眠(另一個問題)保證寫入是在讀取之前完成的,但您需要告訴編譯器同步此變數。
在 C 中,確保一個執行緒看到更改的簡單方法是使用atomic<int>. 如果您不這樣做,其他執行緒可能永遠不會看到更改。這種更改的隱藏可能是由于在編譯時對代碼進行了本地優化,作業系統決定不重繪 某些記憶體頁面,或者硬體本身決定不需要重新加載記憶體。
放置原子變數可以保證所有這些系統都知道你想做什么。所以,使用它。:-)
從評論中解除:
https://en.cppreference.com/w/cpp/language/memory_model#Threads_and_data_races
具有兩個沖突評估的程式具有資料競爭,除非兩個評估在同一執行緒或同一信號處理程式中執行,或者兩個沖突評估都是原子操作(參見 std::atomic),或者沖突評估之一發生在之前另一個(見 std::memory_order) 如果發生資料競爭,程式的行為是未定義的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/460441.html
