簡體   English   中英

Boost :: Thread / C ++ 11 std :: thread,想要在條件下喚醒輔助線程

[英]Boost::Thread / C++11 std::thread, want to wake worker thread on condition

我正在使用Boost :: thread作為輔助線程。 我想在沒有工作要做時將工作線程置於睡眠狀態,並在有工作要做時立即將其喚醒。 我有兩個保存整數的變量。 當整數相等時,沒有任何工作要做。 當整數不同時,有工作要做。 我當前的代碼如下所示:

int a;
int b;

void worker_thread()
{
    while(true) {
        if(a != b) {
            //...do something
        }
                    //if a == b, then just waste CPU cycles
    }
}

//other code running in the main thread that changes the values of a and b

我嘗試使用條件變量,並在a == b時讓工作線程進入睡眠狀態。 問題是存在比賽條件。 這是一個示例情況:

  1. 輔助線程評估if(a == b),發現它是正確的。
  2. 主線程將a和/或b更改為不再相等。 在輔助線程上調用notify_one()。
  3. 工作線程會忽略notify_one(),因為它仍然處於喚醒狀態。
  4. 工作線程進入睡眠狀態。 僵局

如果我可以避免使用條件變量,那會更好,因為我實際上不需要鎖定任何東西。 但是只要a == b,工作線程就進入睡眠狀態,而當a!= b時,喚醒工作線程即可。 有沒有辦法做到這一點?

似乎您沒有正確同步訪問:當在工作線程中讀取ab時,至少在訪問與生產者共享的值時,您需要獲取一個鎖:因為工作線程,主線程不能更改ab 如果它們不相等,則工作線程可以釋放鎖並攪亂處理值。 如果它們相等, 在保持鎖定的情況下,工作線程改為對條件變量使用wait() 條件變量的主要功能是自動釋放鎖並進入睡眠狀態。

當主線程更新a和/或b它獲取鎖,進行更改,釋放鎖並通知工作線程。 工作線程顯然沒有持有該鎖,而是在下一次檢查到期時或由於通知的結果而獲得了該鎖,檢查了值的狀態,然后使用wait()或處理這些值。

正確完成操作后,就不可能出現競爭狀況!

我錯過了您的主要困惑:“因為我實際上不需要鎖定任何東西”! 好吧,當您有兩個線程可以同時訪問相同的值,並且至少其中一個正在修改該值時,如果沒有同步,則將導致數據爭用。 具有數據爭用的任何程序都具有未定義的行為。 換種說法:即使您只想將一個bool值從一個線程發送到另一個線程,也需要同步。 同步不必采取鎖定的形式(例如,可以使用原子變量來同步值),但是進行非平凡的通信,例如,涉及兩個int而不是僅使用原子的一個通常很難! 您幾乎肯定使用鎖。 但是,您可能尚未發現這種強烈的願望。

要考慮的事情:

  1. 您的線程根本沒有理由入睡嗎?
  2. 為什么不啟動一個新線程,讓它在完成工作后自然死亡呢?
  3. 如果在任何時間點只有一個代碼路徑處於活動狀態(所有其他線程都處於睡眠狀態),則您的設計將不允許並發。

最后,如果您使用的是線程之間共享的變量,則應該使用atomic 這將確保對值的訪問被同步。

暫無
暫無

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

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