程序在 C++11 中使用条件变量进入死锁



我目前正在尝试学习如何使用condition_variable进行线程同步。为了进行测试,我制作了如下所示的演示应用程序。当我启动它时,它遇到了死锁。我知道发生这种情况的位置,但我无法理解为什么会发生死锁。

我知道当条件不为真时,condition_variablewait函数会自动解锁互斥锁,所以在第二遍中不应该阻塞主线程。但事实就是如此。

谁能解释为什么?

#include <thread>
#include <condition_variable>
#include <iostream>
bool flag = false;
std::mutex g_mutex;
std::condition_variable cv;

void threadProc()
{
    std::unique_lock<std::mutex> lck(g_mutex);
    while (true)
    {
        static int count = 0;
        std::cout << "wait for flag" << ++count << std::endl;
        cv.wait(lck, []() {return flag; }); // !!!It will blocked at the second round
        std::cout << "flag is true " << count << std::endl;
        flag = false;
        lck.unlock();
    }
}
int main(int argc, char *argv[])
{
    std::thread t(threadProc);
    while (true)
    {
        static int count = 0;
        {
            std::lock_guard<std::mutex> guard(g_mutex); // !!!It will blocked at the second round
            flag = true;
            std::cout << "set flag " << ++count << std::endl;
        }
        cv.notify_one();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    t.join();
    return 0;
}

我知道当条件不为真时,condition_variable的等待函数会自动解锁互斥锁。

嗯...,

是的...,为了绝对清楚,cv.wait(lck, f)这样做:

while(! f()) {
    cv.wait(lck);
}

每一次呼唤cv.wait(lck)都会;

  • 解锁lck
  • 等到其他线程调用cv.notify_one()cv.notify_all()
  • 重新锁定lck,然后
  • 返回。
您可以通过在

while 循环内移动 unique_lock(...( 语句来解决此问题。就像现在一样,您正在尝试在第 2 轮解锁 lck,但它没有处于锁定状态,因为在第 1 轮之后您再也没有锁定过它。

最新更新