为什么它不会发生死锁

Why it does NOT occur deadlock?

本文关键字:死锁 为什么      更新时间:2023-10-16

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

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

我的输出是:

啪......

锁定弹出()

主线程将推送

锁定按钮()

锁定弹出唤醒。商品: 1

从流行音乐归来

弹出:2

结束

此语句:

 cond_.wait(mlock);

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

正在发生的事情是 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

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