Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 multiple read and one write thread mutex [duplicate]

I have an application, where some STL containers are read in 3 threads, and written in 2. I know there is TBB for multi-threaded containers, but it is not an option in my application.

So I want to make the program thread-safe using std::mutex and my bare hands. This is a simple version of what I did:

int readers = 0; std::mutex write;  // One write, no reads. void write_fun() {     write.lock();// We lock the resource     while(readers > 0){}// We wait till everyone finishes read.     // DO WRITE     write.unlock();// Release }  // Multiple reads, no write void read_fun() {     // We wait if it is being written.     while(!write.try_lock()){}     write.unlock();      readers++;     // do read     readers--; } 

Is this the correct way to do this in C++11?

like image 723
VSZM Avatar asked Nov 11 '13 20:11

VSZM


People also ask

Can two threads share a mutex?

Only one thread can hold the mutex at a time, and the other thread can do no useful work.

Can one thread read/write and change other thread data?

In multiple processes each process operates independently of the others. One thread can read, write or change another thread's data.

Can you lock mutex twice?

To solve your issue, you can use std::recursive_mutex , which can be locked/unlocked multiple times from the same thread.

Can multiple threads lock on a mutex?

The non-member function lock allows to lock more than one mutex object simultaneously, avoiding the potential deadlocks that can happen when multiple threads lock/unlock individual mutex objects in different orders.


2 Answers

Pretty close, couple things to note, in c++ for exception safety and readability, IMO, it is good to use RAII locks. What you really need is a shared_mutex like in boost or coming in c++14.

std::shared_mutex write; //use boost's or c++14   // One write, no reads. void write_fun() {     std::lock_guard<std::shared_mutex> lock(write);     // DO WRITE }  // Multiple reads, no write void read_fun() {     std::shared_lock<std::shared_mutex> lock(write);     // do read } 

If you don't want to use boost @howardhinmant was do kind as to give a link to a reference implementation

like image 192
aaronman Avatar answered Sep 22 '22 14:09

aaronman


This is safe, but still likely not fair or performant:

std::atomic<int> readers; std::mutex write;  // One write, no reads. void write_fun() {     write.lock();// We lock the resource     while(readers > 0){}// We wait till everyone finishes read.     // DO WRITE     write.unlock();// Release }  // Multiple reads, no write void read_fun() {     // We wait if it is being written.     write.lock();     readers++;     write.unlock();      // do read     readers--; } 

A solution with condition variables could avoid busy waiting for readers to fall to 0, left as an exercise for the reader.

like image 36
Casey Avatar answered Sep 22 '22 14:09

Casey