簡體   English   中英

如何正確結束線程?

[英]How to end a thread properly?

我的主程序創建了一個線程。 該線程初始化一些數據,然后進入“while”循環並運行,直到主程序將控制變量設置為“false”。 然后它調用 join() 女巫無休止地阻塞整個代碼。

bool m_ThreadMayRun;

void main(){
   thread mythread = thread(&ThreadFunction);
   //do stuff
   m_ThreadMayRun = false;
   mythread.join(); // this blocks endlessly even when I ask 'joinable' before
}

void ThreadFunction{
   initdata();
   m_ThreadMayRun=true;
   while(m_ThreadMayRun){
   //do stuff that can be / has to be done for ever
   }
   deinitdata();
}
  • 我在這里錯過了什么嗎?
  • 使循環離開主線程的正確解決方案是什么?
  • 是否有必要調用加入?

感謝幫助

您有兩個線程寫入m_ThreadMayRun的競爭條件。 考慮如果首先主線程執行m_ThreadMayRun = false;會發生什么然后你創建的線程執行m_ThreadMayRun = true; ,那么你有一個無限循環。 然而,嚴格來說,這條推理線是無關緊要的,因為當你有競爭條件時,你的代碼會有未定義的行為。

我在這里錯過了什么嗎?

您需要通過使其成為std::atomic<bool>或使用std::mutex來同步對m_ThreadMayRun的訪問,並確保在m_ThreadMayRun = false = true 之后執行m_ThreadMayRun = true; .

PS對於這種情況,最好使用std::condition_variable

問題是訪問bool m_ThreadMayRun; 是不同步的,並且根據 C++ 規則,每個線程可以假設它在線程之間沒有變化。 所以你最終會遇到一場比賽(一種未定義的行為)。

為了明確意圖,使其成為atomic的。

std::atomic<bool> m_ThreadMayRun;

這樣, m_ThreadMayRun的每個加載/存儲都變成了 memory 柵欄,由於原子加載/存儲的獲取/釋放語義,它不僅同步了自己的值,而且還使線程完成的其他工作可見。

盡管線程中的m_ThreadMayRun = true和設置m_ThreadMayRun = false之間仍然可能存在小競爭。 任何一個都可以先執行,有時會導致不希望的結果。 為避免這種情況,請在啟動線程之前將其初始化為true

std::atomic<bool> m_ThreadMayRun;

void main(){
   m_ThreadMayRun = true;
   thread mythread(&ThreadFunction);
   //do stuff
   m_ThreadMayRun = false;
   mythread.join(); // this blocks endlessly even when I ask 'joinable' before
}

void ThreadFunction{
   initdata();
   while(m_ThreadMayRun){
   //do stuff that can be / has to be done for ever
   }
   deinitdata();
}

有關 memory 柵欄和獲取/釋放語義的更多詳細信息,請參閱以下優秀資源:《 C++ Concurrency in Action 》一書和 Herb Sutter 的atomic<>武器談話。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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