C++ C++;队列非锁定

C++ C++;队列非锁定,c++,c++11,libcurl,deque,C++,C++11,Libcurl,Deque,我遇到一个问题,线程a从curl回调接收视频数据并将数据添加到std::deque,而线程B从std::deque读取数据并对其进行处理 我在线程A向其添加数据时锁定std::deque,在线程B从中读取数据时锁定它 一切正常,但几分钟后,我的curl回调最终停止,不再接收任何视频数据。 我假设线程B处理数据花费的时间太长,因此锁定时间太长,因此curl回调最终停止 有没有我可以在C++中使用的队列,在这里我不必在添加和读取时锁定它?? 如果需要,我可以发布我的代码。为了避免锁定,可以使用有界、

我遇到一个问题,线程a从curl回调接收视频数据并将数据添加到
std::deque
,而线程B从
std::deque
读取数据并对其进行处理

我在线程A向其添加数据时锁定
std::deque
,在线程B从中读取数据时锁定它

一切正常,但几分钟后,我的curl回调最终停止,不再接收任何视频数据。
我假设线程B处理数据花费的时间太长,因此锁定时间太长,因此curl回调最终停止

有没有我可以在C++中使用的队列,在这里我不必在添加和读取时锁定它??


如果需要,我可以发布我的代码。

为了避免锁定,可以使用有界、无锁队列。人们可以在boost中找到这样的东西:


检查生产者端的完整队列也可以停止卷曲线程以避免过载。

要避免锁定,可以使用有界的、无锁队列。人们可以在boost中找到这样的东西:


在producer端检查完整队列也可以停止卷曲线程以避免过载。

Boost提供无锁队列,但它们有一些限制,比如只允许存储POD类型

一个常见的解决方案是消费者拥有自己的队列对象,该对象开始为空,并在包含工作时与共享队列对象交换

std::mutex global_queue_mutex;
std::condition_variable work_available;
std::deque<Work> global_queue;

void consumer()
{
  std::deque<Work> local;
  while (true)
  {
    // wait for work to be available and then swap it into local queue
    {
      std::unique_lock<std::mutex> lock(global_queue_mutex);
      work_available.wait(lock, [&]{ return !global_queue.empty(); });
      local.swap(global_queue);
    }
    for (auto& work : local)
    {
      // do work
    }
    local.clear();
  }
}

void producer()
{
  // ...
  {
    std::lock_guard<std::mutex> lock(global_queue_mutex);
    global_queue.push_back(std::move(work));
  }
  work_available.notify_one();
  // ...
}
std::互斥全局队列互斥;
std::条件变量工作可用;
std::deque全局_队列;
无效消费者()
{
std::deque local;
while(true)
{
//等待工作可用,然后将其交换到本地队列中
{
std::唯一锁定(全局队列互斥);
工作可用。等待(锁定,[&]{return!global_queue.empty();});
本地.swap(全局_队列);
}
用于(自动和工作:本地)
{
//工作
}
local.clear();
}
}
无效生产者()
{
// ...
{
std::lock\u guard lock(全局队列互斥);
全局队列。推回(std::move(work));
}
工作可用。通知一个();
// ...
}

消费者只持有锁足够长的时间来检查工作并进行交换,这将非常快。生产者只持有足够长的锁,以将单个项目推到队列上。

Boost提供无锁队列,但它们有一些限制,比如只允许存储POD类型

一个常见的解决方案是消费者拥有自己的队列对象,该对象开始为空,并在包含工作时与共享队列对象交换

std::mutex global_queue_mutex;
std::condition_variable work_available;
std::deque<Work> global_queue;

void consumer()
{
  std::deque<Work> local;
  while (true)
  {
    // wait for work to be available and then swap it into local queue
    {
      std::unique_lock<std::mutex> lock(global_queue_mutex);
      work_available.wait(lock, [&]{ return !global_queue.empty(); });
      local.swap(global_queue);
    }
    for (auto& work : local)
    {
      // do work
    }
    local.clear();
  }
}

void producer()
{
  // ...
  {
    std::lock_guard<std::mutex> lock(global_queue_mutex);
    global_queue.push_back(std::move(work));
  }
  work_available.notify_one();
  // ...
}
std::互斥全局队列互斥;
std::条件变量工作可用;
std::deque全局_队列;
无效消费者()
{
std::deque local;
while(true)
{
//等待工作可用,然后将其交换到本地队列中
{
std::唯一锁定(全局队列互斥);
工作可用。等待(锁定,[&]{return!global_queue.empty();});
本地.swap(全局_队列);
}
用于(自动和工作:本地)
{
//工作
}
local.clear();
}
}
无效生产者()
{
// ...
{
std::lock\u guard lock(全局队列互斥);
全局队列。推回(std::move(work));
}
工作可用。通知一个();
// ...
}

消费者只持有锁足够长的时间来检查工作并进行交换,这将非常快。生产者仅持有锁的时间足以将单个项推送到队列中。

请查看Intel的线程构建块容器,尤其是和。

请查看Intel的线程构建块容器,尤其是和。

一种简单的方法是将指针推到队列中。当您需要处理一个指针时,只在需要弹出指针的时间内使用锁。然后在处理数据之前释放锁。(考虑使用
std::unique_ptr
,这样您就不必手动管理内存。)或者让读卡器拥有自己的
deque
,并且只锁定足够长的时间,以便
swap()
空的deque与共享的deque。交换将比添加或删除项目更快。然后读取器处理队列副本中的所有内容,清空队列,然后再次锁定并与共享队列交换。当您需要处理一个指针时,只在需要弹出指针的时间内使用锁。然后在处理数据之前释放锁。(考虑使用
std::unique_ptr
,这样您就不必手动管理内存。)或者让读卡器拥有自己的
deque
,并且只锁定足够长的时间,以便
swap()
空的deque与共享的deque。交换将比添加或删除项目更快。然后读取器处理队列副本中的所有内容,清空队列,然后再次锁定并与共享队列交换。