C++ 中的线程安全生产者/使用者模式
thread safe producer/consumer pattern in c++
如何开发线程安全的生产者/消费者模式?
在我的例子中,生产者在一个线程中运行,消费者在另一个线程上运行。
std::d eque为此目的安全吗?
我可以在一个线程中push_back到双端的背面,而在另一个线程中push_front吗?
编辑 1
就我而言,我知道 std::d eque 中的最大项目数(例如 10)。有什么方法可以事先为项目保留足够的空间,以便在处理过程中,无需更改队列内存的大小,从而确保当我将数据添加到后面时,前端数据不会发生任何变化?
STL C++容器不是线程安全的:如果你决定使用它们,你需要在推送/弹出元素时使用适当的同步(基本上是std::mutex
和std::lock
)。
或者,您可以使用正确设计的容器(单生产者-单消费者队列应满足您的需求),这里有一个例子:http://www.boost.org/doc/libs/1_58_0/doc/html/lockfree.html
编辑后的插件:
是的,SPSC 队列基本上是一个环形缓冲区,绝对适合您的需求。
如何开发线程安全的生产者/消费者模式?
有几种方法,但使用锁和显示器相当容易掌握,并且没有太多隐藏的警告。标准库有std::unique_lock
、std::lock_guard
和std::condition_variable
来实现该模式。查看 condition_variable 的 cpp首选项页面以获取简单示例。
std::d eque为此目的安全吗?
这不安全。您需要同步。
我可以在一个线程中push_back到双端的背面,而在另一个线程中push_front吗?
当然可以,但您需要同步。当队列为空或只有一个元素时,存在争用条件。此外,当队列已满或缺少一个已满队列时,如果您想限制其大小。
我想你的意思是push_back()
和pop_front()
.
std::deque
本身不是线程安全的。您需要使用std::mutex
序列化访问,以便使用者在生产者尝试推送时不会尝试弹出。
您还应考虑如何处理以下内容:
- 如果
- 消费者在寻找下一项时,如果 deque 为空,它的行为如何?
如果它进入等待状态,则需要一个std::condition_variable
,以便在添加双端面时由生产者通知。您可能还需要处理程序终止,其中使用者正在等待 deque 并且程序被终止。除非你正确地编排事情,否则它可能会"永远等待"。
10 件物品是"piffle",所以我不会为保留空间而烦恼。 std::deque
会自动增长和收缩,因此在构建工作应用程序之前,不要为细粒度调整而烦恼。
过早优化是万恶之源。
注意:目前尚不清楚您如何限制队列大小,但如果生产者填满队列,然后等待它清除回来,您将需要更多的等待和条件以另一种方式返回以进行协调。
- 消费者和生产者问题的双重缓冲
- 生产者使用者在 cpp 中使用互斥锁的问题
- 如何降低生产者获得锁的可能性,而消费者在使用std::condition_variable时无法获得锁?
- 用于免等待生产者和阻塞使用者的环形缓冲区
- 具有单个生产者单一使用者的无锁循环缓冲区
- C++生产者使用者中,同一使用者线程会抓取所有任务
- 如何将第二个使用者添加到基于 pthread 的生产者-使用者设置中?
- 生产者/使用者,如何确保在关闭所有使用者之前耗尽线程安全队列
- 交换缓冲区而不锁定单个生产者和多个使用者
- 经典生产者使用者线程
- 生产者-使用者日志文件输出重复
- 使用条件变量的生产者和使用者线程
- 生产者和使用者函数,用于在操作手册中测试C++并发的线程安全堆栈示例
- C++ - 生产者/使用者仅允许在定义的块中使用
- 使用 sleep() 时,生产者使用者(使用监视器)代码不起作用
- 使用提升线程和循环缓冲区挂起的生产者/使用者
- 为什么某些线程池实现不使用生产者和使用者模型
- Win32线程生产者更新使用者线程
- 如何在生产者-使用者方案中使用提升条件变量
- C++ 中的线程安全生产者/使用者模式