2015-05-09 93 views
2

我沒有看到這個程序有任何實際用法,但在試驗C++ 11併發性和conditional_variables時,我偶然發現了一些我不完全瞭解的東西。C++ 11 std :: condition_variable - notify_one()行爲不如預期?

起初我假定使用notify_one()將允許下面的程序工作。但是,實際上程序在打印完一個後就凍結了。當我切換到使用notify_all()時,程序做了我想要的操作(按順序打印所有自然數)。我確信這個問題已經以各種形式提出。但是我的具體問題是我在doc的哪裏讀錯了。

我認爲notify_one()應該工作,因爲以下聲明。

如果有任何線程正在等待* this,調用notify_one將取消阻塞其中一個等待線程。

下面只看到其中一個線程會在給定的時間被阻塞,對嗎?

class natural_number_printer 
{ 
public: 
    void run() 
    { 
    m_odd_thread = std::thread(
     std::bind(&natural_number_printer::print_odd_natural_numbers, this)); 
    m_even_thread = std::thread(
     std::bind(&natural_number_printer::print_even_natural_numbers, this)); 

    m_odd_thread.join(); 
    m_even_thread.join(); 
    } 

private: 
    std::mutex m_mutex; 
    std::condition_variable m_condition; 

    std::thread m_even_thread; 
    std::thread m_odd_thread; 

private: 
    void print_odd_natural_numbers() 
    { 
    for (unsigned int i = 1; i < 100; ++i) { 
     if (i % 2 == 1) { 
     std::cout << i << " "; 
     m_condition.notify_all(); 
     } else { 
     std::unique_lock<std::mutex> lock(m_mutex); 
     m_condition.wait(lock); 
     } 
    } 
    } 

    void print_even_natural_numbers() 
    { 
    for (unsigned int i = 1; i < 100; ++i) { 
     if (i % 2 == 0) { 
     std::cout << i << " "; 
     m_condition.notify_all(); 
     } else { 
     std::unique_lock<std::mutex> lock(m_mutex); 
     m_condition.wait(lock); 
     } 
    } 
    } 
}; 
+2

您有一個競爭條件 - 如果發生notify()或notify_all(),並且沒有任何條件等待,則不會釋放任何內容。如果線程在通知之後到達,那麼它將會錯過將會釋放它的通知,並且它會停留在那裏。我不確定爲什麼使用'notify_all()'時看不到問題,但有時候這就是競爭條件的本質。 –

+0

@MichaelBurr通過什麼機制可以同步兩個線程的啓動?沒有產生僵局。 –

回答

2

提供的代碼「正常工作」並被設計卡住。原因被在notify_one的documentation

的影響()描述/ notify_all()和 等待()/ wait_for()/ wait_until()發生在一個單一的總訂單,所以 它notify_one是不可能()例如被延遲,並且 取消阻塞了一個線程,該線程剛剛在調用 notify_one()之後等待。

的一步一步的邏輯是

  1. print_odd_natural_numbers線程啓動
  2. print_even_natural_numbers線程也開始。
  3. m_condition.notify_all();print_even_natural_numbers之前執行print_odd_natural_numbers線程到達m_condition.wait(lock);行。
  4. m_condition.wait(lock);print_odd_natural_numbers被執行且線程卡住了。
  5. m_condition.wait(lock);print_even_natural_numbers被執行,線程也卡住了。
相關問題