C++ 中的线程安全生产者/使用者模式

thread safe producer/consumer pattern in c++

本文关键字:生产者 使用者 模式 安全生产 安全 线程 C++      更新时间:2023-10-16

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

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

std::d eque为此目的安全吗?

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

编辑 1

就我而言,我知道 std::d eque 中的最大项目数(例如 10)。有什么方法可以事先为项目保留足够的空间,以便在处理过程中,无需更改队列内存的大小,从而确保当我将数据添加到后面时,前端数据不会发生任何变化?

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

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

编辑后的插件:

是的,SPSC 队列基本上是一个环形缓冲区,绝对适合您的需求。

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

有几种方法,但使用锁和显示器相当容易掌握,并且没有太多隐藏的警告。标准库有std::unique_lockstd::lock_guardstd::condition_variable来实现该模式。查看 condition_variable 的 cpp首选项页面以获取简单示例。

std::d eque为此目的安全吗?

这不安全。您需要同步。

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

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

我想你的意思是push_back()pop_front().

std::deque本身不是线程安全的。您需要使用std::mutex序列化访问,以便使用者在生产者尝试推送时不会尝试弹出。

您还应考虑如何处理以下内容:

    如果
  1. 消费者在寻找下一项时,如果 deque 为空,它的行为如何?

如果它进入等待状态,则需要一个std::condition_variable,以便在添加双端面时由生产者通知。您可能还需要处理程序终止,其中使用者正在等待 deque 并且程序被终止。除非你正确地编排事情,否则它可能会"永远等待"。

10 件物品是"piffle",所以我不会为保留空间而烦恼。 std::deque会自动增长和收缩,因此在构建工作应用程序之前,不要为细粒度调整而烦恼。

过早优化是万恶之源。

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