Shared Mutex
-
std::shared_mutexis defined in<shared_mutex> -
It can be locked in two different ways:
-
Exclusive lock
- No other thread may acquire a lock
- No other thread can enter a critical section
-
Shared lock
- Other threads may acquire a shared lock
- They can execute critical sections concurrently
Exclusive lock
-
std::lock_guard<std::shared_mutex> -
std::unique_lock<std::shared_mutex> -
Only this thread can execute a critical section
- Other threads must wait until the thread releases its exclusive lock
-
It can only acquire an exclusive lock when the mutex is unlocked
- If other threads have shared or exclusive locks
- This thread must wait until all the locks are released
Shared lock
std::shared_lock<std::shared_mutex>- A thread which has a shared lock can enter a critical section
- It can only acquire a shared lock if there are no exclusive locks
- If another thread has an exclusive lock, this thread must wait until the exclusive lock is released
shared_mutex usage
std::shared_mutex shmut;
void write() {
std::lock_guard lck_guard(shmut); // Write thread with exclusive lock
}
void read() {
std::shared_lock sh_lck(shmut); // Read thread with shared lock
}
In this code, the readers were able to sleep concurrently.
#include <shared_mutex>
#include <thread>
#include <vector>
std::shared_mutex shmut;
int x = 0;
void write() {
std::lock_guard<std::shared_mutex> lck_guard(shmut);
++x;
}
void read() {
std::shared_lock<std::shared_mutex> lck_guard(shmut);
using namespace std::literals;
std::this_thread::sleep_for(100ms);
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 20; ++i) {
threads.push_back(std::thread(read));
}
threads.push_back(std::thread(write));
threads.push_back(std::thread(write));
for (int i = 0; i < 20; ++i) {
threads.push_back(std::thread(read));
}
for (auto &thr : threads) {
thr.join();
}
}
std::shared_mutex Member Functions
-
Exclusive locking
- lock()
- try_lock()
- unlock()
-
Shared locking
- lock_shared()
- try_lock_shared()
- unlock_shared()
Data Race Avoidance
-
The writer thread cannot get an exclusive lock
- Until all other threads release their locks
- Those threads have now left their critical sections
-
The writer thread acquires an exclusive lock
- It enters the critical section
- Reader threads cannot get a shared lock
- Writer threads cannot get an exclusive lock
- Until this thread releases its lock
-
The writer thread releases its exclusive lock
- It has now left its critical section
-
The reader thread cannot get a shared lock
- Until a writer thread releases its exclusive lock
- The writer thread has now left its critical section
-
The reader thread acquires a shared lock
- It enters the critical section
- Other reader threads can also get a shared lock
-
There is no scenario in which there is a data race
- Reader and writer threads cannot interleave in a critical section
Pros and Cons of std::shared_mutex
- Uses more memory than
std::mutex - Slower than
std::mutex - Best suited to situations where
- Reader threads greatly outnumber writer threads
- Read operations take a long time