如何开发线程安全的生产者/消费者模式?
就我而言,生产者在一个线程中运行,而消费者在另一个线程上运行。
std :: deque是否可以安全用于此目的?
我可以在一个线程中将push_back推送到deque的后面,在另一个线程中推送push_front吗?
就我而言,我知道std :: deque中的最大项目数(例如10)。有没有什么方法可以预先为项目保留足够的空间,所以在处理过程中,没有必要改变队列内存的大小,因此确保当我添加推送数据时,前端数据不会发生变化?
答案 0 :(得分:2)
STL C ++容器不是线程安全的:如果您决定使用它们,则在推送/弹出元素时需要使用适当的同步(基本上是std::mutex
和std::lock
)。
或者你可以使用设计合理的容器(单一生产者 - 单一消费者队列应该符合你的需要),这里有一个例子:http://www.boost.org/doc/libs/1_58_0/doc/html/lockfree.html
编辑后插件:
是的,SPSC队列基本上是一个环形缓冲区,最终满足您的需求。
答案 1 :(得分:1)
如何开发线程安全的生产者/消费者模式?
有几种方法,但使用locks and monitors相当容易掌握,并没有很多隐藏的警告。标准库包含std::unique_lock
,std::lock_guard
和std::condition_variable
来实现模式。有关简单示例,请查看condition_variable的cppreference页面。
std :: deque是否可以安全用于此目的?
不安全。你需要同步。
我可以在一个线程中将push_back推送到deque的后面,在另一个线程中推送push_front吗?
当然,但你需要同步。当队列为空或只有一个元素时,存在竞争条件。此外,当队列已满或短缺时,如果您想限制它的大小。
答案 2 :(得分:0)
我认为您的意思是push_back()
和pop_front()
。
std::deque
本身不是线程安全的。
您需要使用std::mutex
序列化访问,以便消费者在生产者尝试推送时不会尝试弹出。
您还应该考虑如何处理以下内容:
如果它进入等待状态,那么当deque被添加到时,你需要生产者通知std::condition_variable
。
您可能还需要处理程序终止,其中消费者正在等待双端队列并且程序终止。除非你正确地协调事情,否则它可能会“永远等待”。
10项是'piffle',所以我不打扰预留空间。 std::deque
会自动增长和缩小,因此在构建工作应用程序之前,不要再进行细粒度调整。
过早优化是万恶之源。
注意:目前尚不清楚如何限制队列大小,但是如果生产者填满队列,然后等待它清除,那么你需要更多的等待和条件以反过来的方式进行协调。