2015-08-16 49 views
2

我正在閱讀使用condition_variablehere的示例代碼。我張貼下面的代碼:爲什麼lock_guard可以通過unique_lock獲取已經鎖定的互斥鎖?

std::mutex m; 
std::condition_variable cv; 
std::string data; 
bool ready = false; 
bool processed = false; 

void worker_thread() 
{ 
    // Wait until main() sends data 
    std::cout << "------------------------\n"; 
    std::unique_lock<std::mutex> lk(m); 
    cv.wait(lk, []{return ready;}); 

    // after the wait, we own the lock. 
    std::cout << "Worker thread is processing data\n"; 
    data += " after processing"; 

    // Send data back to main() 
    processed = true; 
    std::cout << "Worker thread signals data processing completed\n"; 

    // Manual unlocking is done before notifying, to avoid waking up 
    // the waiting thread only to block again (see notify_one for details) 
    lk.unlock(); 
    cv.notify_one(); 
} 

int main() 
{ 
    std::thread worker(worker_thread); 

    data = "Example data"; 
    // send data to the worker thread 
    { 
     std::lock_guard<std::mutex> lk(m); 
     ready = true; 
     std::cout << "main() signals data ready for processing\n"; 
    } 
    cv.notify_one(); 

    // wait for the worker 
    { 
     std::unique_lock<std::mutex> lk(m); 
     cv.wait(lk, []{return processed;}); 
    } 
    std::cout << "Back in main(), data = " << data << '\n'; 

    worker.join(); 

    return 0; 
} 

我的問題是worker_thread是首次推出,所以我將承擔互斥mworker_thread鎖定,但爲什麼在main互斥m仍然可以通過lock_guard鎖定?

+0

是不是*互斥*的整點多線程可以嘗試將其鎖定? –

+0

如果我有意讓'main'睡眠一段時間以確保'worker_thread'首先運行,它仍然輸出'main()信號數據準備好處理',爲什麼? – Allanqunzi

回答

6

條件變量只是三腳架的一部分。

這三部分是狀態變量,狀態和守護狀態的互斥體。

條件變量提供了一種機制來通知狀態何時改變。

該操作使用所有3:

cv.wait(lk, []{return ready;}) 

條件變量的方法需要一個鎖(它必須已經獲得),和一個拉姆達(其測試的狀態)。

wait方法,所述lk解鎖直到條件變量檢測消息(其可以是僞)。當它檢測到一條消息時,它會重新鎖定互斥鎖並運行測試(其目標是確定檢測是否爲虛假的)。如果測試失敗,它會解鎖並再次等待:如果測試通過,它將鎖定鎖定並退出。

還有「測試扔」路徑,根據您的代碼實現的標準版本(C++ 11有缺陷,IIRC),導致不同的鎖定狀態。

你錯過了最重要的事情是,wait解鎖傳遞進來的互斥。

+0

非常感謝!我完全錯過了!我總是爲某些令人驚歎的人在如此短的時間內提供清楚的解釋和對C++的深刻理解而感到驚訝。 – Allanqunzi

相關問題