【问题标题】:is std::queue thread safe with producer and multiple consumers对于生产者和多个消费者来说,std::queue 线程是安全的吗
【发布时间】:2014-02-13 15:28:52
【问题描述】:

如何使队列线程安全?我需要推/弹出/前/后并清除。 boost中是否有类似的东西?

我有一个生产者和一个或多个消费者。

【问题讨论】:

标签: c++ boost queue containers boost-thread


【解决方案1】:

std::queue 如果一个或多个线程正在写入,则不是线程安全的。而且它的接口不利于线程安全的实现,因为它有pop()size()empty()等单独的方法,必须在外部同步。

一种常见的方法*是实现一个具有更简单接口的队列类型,并在内部使用锁定机制来提供同步。

* 搜索“并发队列 C++”应该会产生很多结果。我实现了一个非常简单的玩具 here,其限制是仅使用标准 C++。另请参阅 Anthony Williams 的著作C++ concurrency in action,以及他的博客。

【讨论】:

  • 感谢您的链接!很好的解释。
【解决方案2】:

您必须保护对std::queue 的访问。如果你使用 boost 保护它使用boost::mutex。现在,如果您有多个读者和一个作者线程,请查看boost::shared_lock(读者)和boost::unique_lock(作者)。

但是,如果您遇到编写器线程不足的情况,请查看 boost::shared_mutex

【讨论】:

  • 我怀疑多个读者可以同时安全地读取队列。对于这个问题,我相信读者会从队列中弹出项目。弹出操作会修改队列,因此必须在队列上持有排他锁。在其他上下文中,“阅读器”一词用于表示不执行任何修改并仅查看值的代码。如果在这个问题中,读者调用 peek 而不是 pop,那么他们满足这个条件并且共享锁可以工作。
  • @Jason,一种可能的解决方案可能是具有原子 CAS 机制的可变成员标志,该机制允许每个读取器线程处理队列中的一个唯一项目而不会弹出,以及定期清理阶段(在排他锁)可以帮助清理已处理的项目。
【解决方案3】:

在 boost 1.53 中有一个 lockfee 队列 @9​​87654321@,没有这样的互斥锁或 smth。

【讨论】:

  • 仅适用于 PODS 等 :(
【解决方案4】:

你必须保护它,例如在 每个 操作上使用std::mutex。如果您还没有 C++11,Boost 将是一个替代方案。

【讨论】:

  • 即便如此,仍需要一些额外的同步(例如,您想在弹出之前检查队列是否为空。这不是原子的,因此即使单个操作已同步也可能会失败)。
猜你喜欢
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多