首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >`std::condition_var::notify_all`死锁

`std::condition_var::notify_all`死锁
EN

Stack Overflow用户
提问于 2022-01-11 13:43:23
回答 1查看 161关注 0票数 2

我有cpp代码,其中一个线程生成数据,将数据推入队列,而另一个线程在将数据传递给其他库进行处理之前使用它。

代码语言:javascript
复制
std::mutex lock;
std::condition_variable new_data;
std::vector<uint8_t> pending_bytes;
bool data_done=false;

// producer
  void add_bytes(size_t byte_count, const void *data)
  {
    if (byte_count == 0)
        return;

    std::lock_guard<std::mutex> guard(lock);
    uint8_t *typed_data = (uint8_t *)data;
    pending_bytes.insert(pending_bytes.end(), typed_data,
                               typed_data + byte_count);

    new_data.notify_all();
  }

  void finish()
  {
    std::lock_guard<std::mutex> guard(lock);

    data_done = true;
    new_data.notify_all();
  }

// consumer
Result *process(void)
{
  data_processor = std::unique_ptr<Processor>(new Processor());

  bool done = false;
  while (!done)
  {
    std::unique_lock<std::mutex> guard(lock);
    new_data.wait(guard, [&]() {return data_done || pending_bytes.size() > 0;});

    size_t byte_count = pending_bytes.size();
    std::vector<uint8_t> data_copy;
    if (byte_count > 0)
    {
      data_copy = pending_bytes; // vector copies on assignment
      pending_bytes.clear();
    }

    done = data_done;
    guard.unlock();

    if (byte_count > 0)
    {
      data_processor->process(byte_count, data_copy.data());
    }
  }

  return data_processor->finish();
}

其中Processor是一个相当复杂的类,具有大量多线程处理,但据我所见,它应该与上面的代码分开。

现在,有时代码会死锁,而我正试图找出竞争的条件。我最大的线索是,生产者线程似乎卡在notify_all()下。在GDB中,我得到以下回溯,显示notify_all正在等待什么:

代码语言:javascript
复制
[Switching to thread 3 (Thread 0x7fffe8d4c700 (LWP 45177))]

#0  0x00007ffff6a4654d in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00007ffff6a44240 in pthread_cond_broadcast@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#2  0x00007ffff67e1b29 in std::condition_variable::notify_all() () from /lib64/libstdc++.so.6
#3  0x0000000001221177 in add_bytes (data=0x7fffe8d4ba70, byte_count=256,
    this=0x7fffc00dbb80) at Client/file.cpp:213

同时拥有锁

代码语言:javascript
复制
(gdb) p lock
$12 = {<std::__mutex_base> = {_M_mutex = {__data = {__lock = 1, __count = 0, __owner = 45177, __nusers = 1, __kind = 0,
        __spins = 0, __elision = 0, __list = {__prev = 0x0, __next = 0x0}},

在条件变量等待中等待另一个线程。

代码语言:javascript
复制
[Switching to thread 5 (Thread 0x7fffe7d4a700 (LWP 45180))]
#0  0x00007ffff6a43a35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
(gdb) bt
#0  0x00007ffff6a43a35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007ffff67e1aec in std::condition_variable::wait(std::unique_lock<std::mutex>&) () from /lib64/libstdc++.so.6
#2  0x000000000121f9a6 in std::condition_variable::wait<[...]::{lambda()#1}>(std::
unique_lock<std::mutex>&, [...]::{lambda()#1}) (__p=..., __lock=...,
    this=0x7fffc00dbb28) at /opt/rh/devtoolset-9/root/usr/include/c++/9/bits/std_mutex.h:104

还有另外两个线程运行在Process数据部分下,这两个线程也挂在pthread_cond_wait上,但据我所知,它们不共享任何同步素数(并且只是等待对processor->add_dataprocessor->finish的调用)-- notify_all在等待什么?或者找到罪犯的方法?

编辑:我在这里用一个虚拟处理器复制了代码:https://onlinegdb.com/lp36ewyRSP,但是,和预期的一样,这并没有重现问题,所以我假设还有更复杂的事情发生。可能只是时间不同,但是condition_variableOpenMP之间的一些交互(由真正的处理器使用)可能会导致这种情况吗?

EN

回答 1

Stack Overflow用户

发布于 2022-01-11 17:58:53

在我看来,在调用notify_all (https://en.cppreference.com/w/cpp/thread/condition_variable)之前,您应该在生产者中解锁互斥锁。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70667839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档