Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/254.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果我评论“为什么程序会陷入僵局?”;而";块“怎么说?”;“收益率”;它的效果如何?_C++_Deadlock_Condition Variable - Fatal编程技术网

C++ 如果我评论“为什么程序会陷入僵局?”;而";块“怎么说?”;“收益率”;它的效果如何?

C++ 如果我评论“为什么程序会陷入僵局?”;而";块“怎么说?”;“收益率”;它的效果如何?,c++,deadlock,condition-variable,C++,Deadlock,Condition Variable,我正在学习条件变量并运行一些示例。我很好奇,如果我对块进行注释,为什么下面的代码会死锁。这是一个使用condition_变量的简单消费者和生产者示例。我认为这是一个僵局问题,不是吗 #include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; mutex mtx; condition_variab

我正在学习条件变量并运行一些示例。我很好奇,如果我对块进行注释,为什么下面的代码会死锁。这是一个使用condition_变量的简单消费者和生产者示例。我认为这是一个僵局问题,不是吗

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

using namespace std;

mutex mtx;
condition_variable cv;

int cargo = 0;

bool shipment_available()
{
    return cargo != 0;
}

void consume(int cnt)
{
    for (int i = 0; i < cnt; i++)
    {
        unique_lock<mutex> lck(mtx);
        cv.wait(lck, shipment_available);
        printf("%d\n", cargo);
        cargo = 0;
    }
}

int main()
{
    thread consumer_thread(consume, 10);

    for (int i = 0; i < 10; i++)
    {
        //while (shipment_available())    // Dead lock without this block
        //{
        //    std::this_thread::yield();
        //}
        unique_lock<mutex> lck(mtx);
        cargo = i + 1;
        cv.notify_one();
    }

    consumer_thread.join();
}
#包括
#包括
#包括
#包括
使用名称空间std;
互斥mtx;
条件变量cv;
国际货运=0;
bool装运可用()
{
退货!=0;
}
无效消耗(int cnt)
{
对于(int i=0;i

如果我取消对该块的注释,它运行得很好。

因此,请仔细查看以下极有可能出现的情况:

  • main()
    启动使用者线程
  • 在线程可以获取互斥锁之前,
    main()
    将其锁定,增加
    cargo
    ,并触发通知,然后通过作用域旋转十次释放互斥锁
  • main()
    现在运行到
    join
    consumer线程
  • 使用者最终获得互斥锁,并准备等待给定谓词(非零货物)的条件变量
  • 谓词已为true,因此不执行等待
  • 使用者将货物归零,然后通过作用域旋转释放互斥锁
  • 消费者第二次循环,锁定互斥锁,然后检查谓词,只是现在谓词为false,因为
    cargo
    确实为零,所以它等待条件变量(在过程中释放互斥锁),等待永远不会出现的信号。唯一发送该信号的是
    main()
    ,它只是在等待消费者线程加入,而这现在永远不会发生
  • 简言之,您似乎相信条件变量信号叠加在一起。事实并非如此。如果在发布通知时没有人在积极等待通知,则通知将被以太丢失

    最后,这一点很重要,您的“修复”本身是完全错误的。
    shipping\u可用
    函数检查谓词数据(即必须由隐藏在其中的互斥锁保护的数据,不仅用于修改,也用于检查)。检查未锁定互斥锁的
    main
    是否会导致竞争条件


    我的建议是把货物减少一件,而不是把它归零。或者,您可以在归零之前将
    i
    增加
    cargo
    的值,从而加速
    i
    上升到
    cnt
    限制,但您似乎使用了上升的货量,因此,您必须做出相应的其他调整。

    在确认有什么需要等待之前,您不能调用
    等待。这就是互斥的目的。@DavidSchwartz我不确定我是否理解你的评论,David。上述潜在工作流程中是否有遗漏的内容?如果是这样的话,一定要找出答案并把它加进去。我正试图把你想要表达的概念具体化。@DavidSchwartz啊。。。好啊谢谢,非常感谢。我认为这正是原因,因为程序最终只输出“10”,然后陷入困境。这只是一些社论中的示例代码。再次感谢!