Mutex (C++)

In the OS, mutexes and semaphores are kernel resources that provide synchronization services.

Mutex is a specific kind of binary semaphore that is used to provide a locking mechanism. It stands for Mutual Exclusion Object.

The mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads.

Mutex

Mutex as the name hints implies mutual exclusion. A mutex is used to guard shared data such as a linked-list, an array or any simple primitive type. A mutex allows only a single thread to access a resource.

Resources:

Locking functions:

  • lock: locks the mutex, blocks if the mutex is not available, see lock (C++)
  • try_lock: tries to lock the mutex, returns if the mutex is not available
  • unlock: unlocks the mutex

You need to include the <mutex> library to use this functionality.

Here’s an example:

void print_block (int n, char c) {
  // critical section (exclusive access to std::cout signaled by locking mtx):
  mtx.lock();
  for (int i=0; i<n; ++i) { std::cout << c; }
  std::cout << '\n';
  mtx.unlock();
}
 
int main ()
{
  std::thread th1 (print_block,50,'*');
  std::thread th2 (print_block,50,'$');
 
  th1.join();
  th2.join();
 
  return 0;
}

Some more advanced mutexes in C++:

  • shared_time_mutex

shared_time_mutex

The shared_timed_mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads. In contrast to other mutex types which facilitate exclusive access, a shared_timed_mutex has two levels of access:

  • exclusive - only one thread can own the mutex.
  • shared - several threads can share ownership of the same mutex.

Shared mutexes are usually used in situations when multiple readers can access the same resource at the same time without causing data races, but only one writer can do so.

https://en.cppreference.com/w/cpp/thread/shared_timed_mutex

Also look at this https://stackoverflow.com/questions/40207171/why-shared-timed-mutex-is-defined-in-c14-but-shared-mutex-in-c17

https://www.justsoftwaresolutions.co.uk/threading/new-concurrency-features-in-c++14.html

std::lock_guard

https://cplusplus.com/reference/mutex/lock_guard/

The class lock_guard is a mutex wrapper that provides a convenient RAII-style mechanism for owning a mutex for the duration of a scoped block.

// lock_guard example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex, std::lock_guard
#include <stdexcept>      // std::logic_error
 
std::mutex mtx;
 
void print_even (int x) {
  if (x%2==0) std::cout << x << " is even\n";
  else throw (std::logic_error("not even"));
}
 
void print_thread_id (int id) {
  try {
    // using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:
    std::lock_guard<std::mutex> lck (mtx);
    print_even(id);
  }
  catch (std::logic_error&) {
    std::cout << "[exception caught]\n";
  }
}
 
int main ()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_thread_id,i+1);
 
  for (auto& th : threads) th.join();
 
  return 0;
}