簡體   English   中英

C ++無鎖線程同步

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM