thread safe producer/consumer pattern in c++

3.7k views Asked by At

How Can I develop a producer/ consumer pattern which is thread safe?

in my case, the producer runs in a thread and the consumer runs on another thread.

Is std::deque is safe for this purpose?

can I push_back to the back of a deque in one thread and push_front in another thread?

Edit 1

In my case, I know the maximum number of items in the std::deque (for example 10). Is there any way that I can reserve enough space for items beforehand so during processing, there was no need to change the size of queue memory and hence make sure when I am adding pushing data to back, no change could be happen on front data?

3

There are 3 answers

0
eerorika On

How Can I develop a producer/ consumer pattern which is thread safe?

There are several ways, but using locks and monitors is fairly easy to grasp and doesn't have many hidden caveats. The standard library has std::unique_lock, std::lock_guard and std::condition_variable to implement the pattern. Check out the cppreference page of condition_variable for simple example.

Is std::deque is safe for this purpose?

It's not safe. You need synchronization.

can I push_back to the back of a deque in one thread and push_front in another thread?

Sure, but you need synchronization. There is a race condition when the queue is empty or has only one element. Also when the queue is full or one short of full in case you want to limit it's size.

0
Persixty On

I think you mean push_back() and pop_front().

std::deque is not thread-safe on its own. You will need to serialise access using an std::mutex so the consumer isn't trying to pop while the producer is trying to push.

You should also consider how you handle the following:

  1. How does the consumer behave if the deque is empty when it looks for the next item?

If it enters a wait state then you will need a std::condition_variable to be notified by the producer when the deque has been added to. You may also need to handle program termination in which the consumer is waiting on the deque and the program is terminated. It could be left 'waiting forever' unless you orchestrate things correctly.

10 items is 'piffle' so I wouldn't bother about reserving space. std::deque grows and shrinks automatically so don't bother with fine grain tuning until you've built a working application.

Premature optimization is the root of all evil.

NB: It's not clear how your limiting the queue size but if the producer fills up the queue and then waits for it to clear back down you'll need more waits and conditions coming back the other way to coordinate.

0
Sigi On

STL C++ containers are not thread-safe: if you decide for them, you need to use proper synchronizations (basically std::mutex and std::lock) when pushing/popping elements.

Alternatively you can use properly designed containers (single-producer-single-consumer queues should fit your needs), one example of them here: http://www.boost.org/doc/libs/1_58_0/doc/html/lockfree.html

addon after your EDIT:

yep, a SPSC queue is basically a ring buffer and definitively fits you needs.