Mutex Class
- The C++ Standard Library provides an
std::mutexclass- Defined in
<mutex>
- Defined in
- A mutex object must be visible in all task functions which uses it
- It must also be defined outside the task functions
- Global/static variable with global function
- Class data member with member task function
- Variable captured by reference with lambda expressions
std::mutex Interface
-
Three main member functions:
-
lock()- Tries to lock the mutex
- If not successful, waits until it locks the mutex
-
try_lock()- Tries to lock the mutex
- Returns immediately if not successful
-
unlock()- Releases the lock on the mutex
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
std::mutex task_mutex;
void task(const std::string &str) {
for (int i = 0; i < 5; ++i) {
// Lock mutex before critical section
task_mutex.lock();
std::cout << str[0] << str[1] << str[2] << std::endl;
// Unlock mutex after critical section
task_mutex.unlock();
}
}
int main() {
std::thread thr1(task, "abc");
std::thread thr2(task, "def");
std::thread thr3(task, "xyz");
thr1.join();
thr2.join();
thr3.join();
}
- The output is no longer scrambled up
- The accesses to the critical section are synchronized
- This prevents the threads from interfering with each other
std::mutex::try_lock()
-
try_lock()returns immediately- Returns true if it locked the mutex
- Returns false if it could not lock the mutex
-
Usually called in a loop
#include <iostream>
#include <mutex>
#include <thread>
using namespace std::literals;
std::mutex the_mutex;
void task1() {
std::cout << "Task1 trying to lock the mutex\n";
the_mutex.lock();
std::cout << "Task1 has locked the mutex\n";
std::this_thread::sleep_for(500ms);
std::cout << "Task1 unlocking the mutex\n";
the_mutex.unlock();
}
void task2() {
std::this_thread::sleep_for(100ms);
std::cout << "Task2 trying to lock the mutex\n";
while (!the_mutex.try_lock()) {
std::cout << "Task2 could not lock the mutex\n";
std::this_thread::sleep_for(100ms);
}
std::cout << "Task2 has locked the mutex\n";
the_mutex.unlock();
}
int main() {
std::thread thr1(task1);
std::thread thr2(task2);
thr1.join();
thr2.join();
}