2015-01-15 93 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); 

在等待期间实际解锁互斥量,并重新获取一次信号锁定。这就是为什么你没有任何僵局。