为什么它不会发生死锁?

Why it does NOT occur deadlock?

代码同时从两个不同的线程获取相同的互斥量。 我知道应该发生死锁。为什么没有发生?

#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;
}

我的输出是:

popping...

lock pop()

main thread will push

lock push()

pushed

lock pop awake. Items: 1

returning from pop

popped: 2

end

死锁需要在不同线程中以不同顺序获取两个互斥体。我在您的代码中只看到一个互斥体。

正在发生的事情是 std::condition_variable::wait 正在释放互斥量。然后线程等待 notify_one 调用,这将释放条件并重新获取互斥锁。

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

"There must be at least one thread that is waiting for a condition to become true. The waiting thread must first acquire a unique_lock. This lock is passed to the wait() method, that releases the mutex and suspends the thread until the condition variable is signaled. When that happens the thread is awaken and the lock is re-acquired." http://www.codeproject.com/Articles/598695/Cplusplus-threads-locks-and-condition-variables

这条语句:

 cond_.wait(mlock);

实际上在等待期间解锁互斥锁,并在发出信号后重新获取锁。这就是为什么你没有任何死锁。