【问题标题】:thread safe producer/consumer pattern in c++C ++中的线程安全生产者/消费者模式
【发布时间】:2015-08-26 19:45:21
【问题描述】:

如何开发线程安全的生产者/消费者模式?

在我的例子中,生产者在一个线程中运行,而消费者在另一个线程中运行。

std::deque 是否安全?

我可以在一个线程中 push_back 到双端队列的后面,在另一个线程中 push_front 吗?

编辑 1

就我而言,我知道 std::deque 中的最大项目数(例如 10)。有什么办法可以预先为项目保留足够的空间,所以在处理过程中,不需要更改队列内存的大小,因此确保当我将数据添加到后面时,前面的数据不会发生变化?

【问题讨论】:

  • std::deque 就像任何其他 STL 容器默认情况下不是线程安全的。推入时需要make it thread safe。
  • @Vinzenz .. 并从中弹出。
  • 我在github.com/mikeando/Thread-Utils 有一个单一生产者多消费者队列的简单实现 - 它可能已损坏,可能无法执行您想要的操作等。而且它的旧版本不使用漂亮的 C++ 11 个功能,但我建议使用 Sigismondo 答案中的增强功能(不要认为增强功能在我写我的时候存在)

标签: c++ design-patterns std producer-consumer


【解决方案1】:

STL C++ 容器不是线程安全的:如果您决定使用它们,则在推送/弹出元素时需要使用适当的同步(基本上是 std::mutex 和 std::lock)。

或者,您可以使用设计合理的容器(单生产者单消费者队列应该满足您的需求),这里有一个示例:http://www.boost.org/doc/libs/1_58_0/doc/html/lockfree.html

编辑后的插件:

是的,SPSC 队列基本上是一个环形缓冲区,完全符合您的需求。

【讨论】:

    【解决方案2】:

    如何开发线程安全的生产者/消费者模式?

    有多种方法,但使用locks and monitors 相当容易掌握并且没有太多隐藏的警告。标准库有std::unique_lock、std::lock_guard 和std::condition_variable 来实现该模式。查看condition_variable的cppreference页面以获取简单示例。

    std::deque 是否安全?

    这不安全。您需要同步。

    我可以在一个线程中 push_back 到双端队列的后面,在另一个线程中 push_front 吗?

    当然可以,但是您需要同步。当队列为空或只有一个元素时,存在竞争条件。此外,当队列已满或未满时,以防您想限制其大小。

    【讨论】:

      【解决方案3】:

      我想你的意思是push_back() 和pop_front()。

      std::deque 本身不是线程安全的。 您需要使用std::mutex 对访问进行序列化,这样消费者就不会在生产者尝试推送时尝试弹出。

      您还应该考虑如何处理以下问题:

      1. 如果双端队列为空,消费者在查找下一项时会如何表现?

      如果它进入等待状态,那么你需要一个std::condition_variable,以便在添加双端队列时由生产者通知。 您可能还需要处理程序终止,其中消费者在双端队列上等待并且程序终止。除非您正确安排事情,否则它可能会“永远等待”。

      10 个项目是“piffle”,所以我不会为保留空间而烦恼。 std::deque 会自动增长和缩小,因此在构建一个可以工作的应用程序之前不要进行细粒度调整。

      过早的优化是万恶之源。

      注意:目前尚不清楚您如何限制队列大小,但如果生产者填满队列然后等待它清除回来,您将需要更多的等待和条件以其他方式返回以进行协调。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-24
        • 2016-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多