Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

condition_variable without mutex in a lock-free implementation

I have a lock-free single producer multiple consumer queue implemented using std::atomics in a way similar to Herb Sutters CPPCon2014 talk.

Sometimes, the producer is too slow to feed all consumers, therefore consumers can starve. I want to prevent starved consumers to bang on the queue, therefore I added a sleep for 10ms. This value is arbitrary and not optimal. I would like to use a signal that the consumer can send to the producer once there is a free slot in the queue again. In a lock based implementation, I would naturally use std::condition_variable for this task. However now in my lock-free implementation I am not sure, if it is the right design choice to introduce a mutex, only to be able to use std::condition_variable.

I just want to ask you, if a mutex is the right way to go in this case?

Edit: I have a single producer, which is never sleeping. And there are multiple consumer, who go to sleep if they starve. Thus the whole system is always making progress, therefore I think it is lock-free. My current solution is to do this in the consumers GetData Function:
std::unique_lock<std::mutex> lk(_idleMutex); _readSetAvailableCV.wait(lk);

And this in the producer Thread once new data is ready:
_readSetAvailableCV.notify_all();

like image 501
bodzcount Avatar asked Oct 04 '15 16:10

bodzcount


2 Answers

If most of your threads are just waiting for the producer to enqueue a resource, I'm not that sure a lock-free implementation is even worth the effort. most of the time, your threads will sleep, they won't fight each other for the queue lock.

That is why I think (from the amount of data you have supplied), changing everything to work with a mutex + conditional_variable is just fine. When the producer enqueues a resource it notifies just one thread (with notify_one()) and releases the queue lock. The consumer that locks the queue dequeues a resource and returns to sleep if the queue is empty again. There shouldn't be any real "friction" between the threads (if your producer is slow) so I'd go with that.

like image 182
David Haim Avatar answered Nov 15 '22 00:11

David Haim


I just watched this CPPCON video about the concurrency TS: Artur Laksberg @cppcon2015

Somewhere in the middle of this talk Artur explains how exactly my problem could be solved with barriers and latches. He also shows an existing workaround using a condition_variable in the way i did. He underlines some weakpoints about the condition_variable used for this purpose, like spurious wake ups and missing notify signals before you enter wait. However in my application, these limitations are no problem, so that I think for now, I will use the solution that I mentioned in the edit of my post - until latches/barrierers are available. Thanks everybody for commenting.

like image 24
bodzcount Avatar answered Nov 14 '22 23:11

bodzcount