[英]C++ lock-free thread synchronization
我有以下代碼:
bool sync=false;
int* ptr=NULL;
std::thread t([&](){
do_a(); // long-time operation
while(!sync){
std::atomic_thread_fence(std::memory_order_acquire);
}
do_b(ptr);
});
int val=do_c(); //long-time operation
ptr=&val;
sync=true;
std::atomic_thread_fence(std::memory_order_release);
....
但是當我在多處理器計算機上啟動它時,有時會發生do_b()
從空指針開始的情況。 不能很好地理解這種行為。 編譯器會做一些優化嗎? 還是我用柵欄錯了? 這些柵欄是否確保線程之間的數據同步?
謝謝您的幫助。
您的程序嘗試按該順序寫入兩個存儲位置(ptr,sync)。 但是您還沒有告訴編譯器和/或CPU這是必須的。 您的編譯器可以自由地重新安排內存寫入的順序,以適應其目標(贏得毫無意義的基准測試)。 您的cpu可以自由地重新安排內存寫入以適合其目標(減少總線爭用,無意義的基准測試)。
因此,首先您應該告訴編譯器,實現所需的順序很重要。 您可以使用std :: atomic或可能是volatile指令(*)來完成此操作。
其次,您需要告訴您的CPU,您所依賴的是這些商店的可見順序。 在單個cpu中,程序順序(上方)和可見順序相同。 在多個CPU中,它們不僅不一定相同,而且會隨當前和過去的系統活動而變化。 因此@DanielLangr對圍欄位置的評論。 防護欄通知CPU,在防護欄之后的任何商店之前,必須先看到防護欄之前的所有商店。
(*)以基准為重點的編譯器編寫者已設法將波動降低到幾乎毫無意義,這表明了編譯器編寫者對實際客戶的鄙視。 奇怪的是,事實證明,“依靠機器語言寫那些位”比依靠“ de jour”標准編寫者的工件更容易維護。 “智能鏈接器”的出現最終可能會以30年的標准委員會未能采用的方式來中立系統編程語言。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.