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?
Only one thread can hold the mutex at a time, and the other thread can do no useful work.
In multiple processes each process operates independently of the others. One thread can read, write or change another thread's data.
To solve your issue, you can use std::recursive_mutex , which can be locked/unlocked multiple times from the same thread.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With