Skip to content

C++ Concurrency

Threads

  • std::thread
    • detach won't be able to manage the thread aside from any mutex or shared resources between the different threads. Those detached threads will only exit when the main process is terminated or when top level function exits.

Mutual Exclusion

  • std::mutex
    • protect shared resources and to prevent race conditions.
    • void lock();, block execution until the lock is acquired. usually not called directly: mutex wrapper are used to manage exclusive locking
    • bool try_lock();, returns immediately
  • std::recursive_mutex
    • The same thread cam lock an recursive_mutex multiple times without blocking

Mutex Wrapper

  • std::lock_guard
    • It provides exclusive ownership of a mutex for a scoped duration.
    • The lock is acquired upon construction and automatically released when the object goes out of scope.
    • lock_guard<mutex> guard(my_mutex)
  • std::unique_lock
    • It supports both exclusive ownership and shared ownership of a mutex.
    • Allow manual unlocking, relocking, and transferring of ownership between different scopes or threads.
    • Provides advanced functionalities like timed locking, condition variables, and deadlock avoidance.
    • unique_lock lock(mtx);
  • std::shared_lock
    • Multiple threads can acquire a shared lock on the same mutex
    • Shared locking attempts block if the mutex is locked in exclusive mode
    • Only usable in conjunction with std::shared_mutex
    • shared_lock lock(mtx);
  • std::scoped_lock

    • offers an alternative for lock_guard that provides the ability to lock multiple mutexes using a deadlock avoidance algorithm.
  • Shared mutexes are mostly used to implement read/write-locks
  • Only read accesses are allowed when holding a shared lock
  • Write accesses are only allowed when holding an exclusive lock

Atomic

  • std::atomic
    • An atomic type is mainly a type that implements atomic operations. thread safe and run independently of any other processes.

Futures

  • promise
  • future

    • returned by asynchronous operations (async, packaged_task, promise)
  • task
promise<int> promise;
future<int> future = promise.get_future();
shared_future<int> shared_future = promise.get_future();

promise.set_value(10);
int val = future.get();

Memory Ordering

  • std::memory_order
    • memory_order specifies how memory accesses are to be ordered around an atomic operation.
    • The default behavior of all atomic operations in the library provides for sequentially consistent ordering.
    • memory_order_seq_cst A load operation with this memory order performs an acquire operation, a store performs a release operation
  • Relaxed ordering
  • Release-Acquire ordering
  • Release-Consume ordering
  • Sequentially-consistent ordering