2015-01-15 94 views
2

代碼同時從兩個不同線程獲取相同的互斥量。我知道應該發生死鎖。爲什麼沒有發生?爲什麼它不會發生死鎖?

#include <iostream> 
#include <thread> 
#include <queue> 
#include <mutex> 
#include <condition_variable> 

template <typename T> 
class SafeQueue 
{ 
public: 
    T pop() 
    { 
    std::unique_lock<std::mutex> mlock(mutex_); 
    std::cout << "lock pop()" << std::endl; 
    while (queue_.empty()) 
    { 
     cond_.wait(mlock); 
     std::cout << "lock pop awake. Items: " << queue_.size() << std::endl; 
    } 
    auto item = queue_.front(); 
    queue_.pop(); 
    std::cout << "returning from pop" << std::endl; 
    return item; 
    } 

    void push(const T& item) 
    { 
    std::unique_lock<std::mutex> mlock(mutex_); 
    std::cout << "lock push()" << std::endl; 
    queue_.push(item); 
    mlock.unlock(); 
    cond_.notify_one(); 
    } 
private: 
    std::queue<T> queue_; 
    mutable std::mutex mutex_; 
    std::condition_variable cond_; 
}; 

SafeQueue<int> queue; 

void pop() 
{ 
    std::cout << "popping..." << std::endl; 
    std::cout << "popped: " << queue.pop() << std::endl; 
} 

int main() 
{ 
    std::thread consumerThread(pop); 
    std::this_thread::sleep_for(std::chrono::seconds(3)); 
    std::cout << "main thread will push" << std::endl; 
    queue.push(2); 
    std::cout << "pushed" << std::endl; 
    consumerThread.join(); 
    std::cout << "end" << std::endl << std::endl; 
} 

我的輸出是:

啪......

鎖pop()方法

主線程將推動

鎖推()

鎖彈出清醒。項目:1

從彈出

彈出返回:2

回答

3

發生了什麼是std :: condition_variable :: wait釋放互斥鎖。該線程然後等待notify_one調用,這將釋放條件並重新獲取互斥鎖。

http://en.cppreference.com/w/cpp/thread/condition_variable/wait

「必須有一個等待的狀態,成爲真正的至少一個線程。等待的線程必須首先獲取unique_lock,此鎖被傳遞給wait()方法,該釋放互斥並暫停線程,直到條件變量發出信號,此時線程被喚醒並重新獲取鎖。「 http://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables

0

死鎖要求以不同的順序在不同的線程獲取的兩個互斥。我只在你的代碼中看到一個互斥體。

4

本聲明:

cond_.wait(mlock); 

在等待期間實際解鎖互斥量,並重新獲取一次信號鎖定。這就是爲什麼你沒有任何僵局。