Monday, December 9, 2024

std::mutex, std::lock_guard, std::unique_lock, and std::shared_lock

 In C++, std::mutex, std::lock_guard, std::unique_lock, and std::shared_lock are synchronization primitives used to manage access to shared resources in multithreaded programming. Here's a detailed comparison:


1. std::mutex

  • What it is: A basic locking primitive.
  • Usage: Used to protect shared data from being simultaneously accessed by multiple threads.
  • Pros:
    • Explicit control over locking and unlocking.
    • Lightweight and straightforward.
  • Cons:
    • Manual locking/unlocking can lead to mistakes like forgetting to unlock (risking deadlocks).

Example:

std::mutex mtx;

void threadSafeFunction() {
    mtx.lock();
    // Critical section
    mtx.unlock();
}

2. std::lock_guard

  • What it is: A RAII (Resource Acquisition Is Initialization) wrapper for std::mutex.
  • Usage: Automatically locks the mutex on creation and unlocks it when it goes out of scope.
  • Pros:
    • Reduces risk of forgetting to unlock.
    • Simplifies code by managing the mutex lifecycle automatically.
  • Cons:
    • Less flexible than std::unique_lock.

Example:

std::mutex mtx;

void threadSafeFunction() {
    std::lock_guard<std::mutex> lock(mtx);
    // Critical section
    // Automatically unlocks when `lock` goes out of scope
}

3. std::unique_lock

  • What it is: A more flexible RAII wrapper for std::mutex.
  • Usage: Provides advanced features like deferred locking, timed locking, and ability to transfer ownership.
  • Pros:
    • Flexibility in lock acquisition and release.
    • Supports features like try_lock and defer_lock.
  • Cons:
    • Slightly heavier than std::lock_guard due to its flexibility.

Example:

std::mutex mtx;

void threadSafeFunction() {
    std::unique_lock<std::mutex> lock(mtx);
    // Critical section
    lock.unlock();  // Manual unlocking if needed
    // Can also relock later
    lock.lock();
}

4. std::shared_lock

  • What it is: A lock for std::shared_mutex that allows multiple threads to acquire shared (read-only) access.
  • Usage: Use with std::shared_mutex when you need shared (read) and exclusive (write) locking.
  • Pros:
    • Optimized for scenarios where multiple threads read and fewer write.
  • Cons:
    • Requires std::shared_mutex, which is slightly heavier than std::mutex.

Example:

#include <shared_mutex>

std::shared_mutex sharedMtx;

void reader() {
    std::shared_lock<std::shared_mutex> lock(sharedMtx);
    // Shared access (read-only)
}

void writer() {
    std::unique_lock<std::shared_mutex> lock(sharedMtx);
    // Exclusive access (write)
}

When to Use What

Use Case Recommended Lock
Basic locking/unlocking std::mutex
Simple RAII-based lock std::lock_guard
Need flexibility (e.g., timed lock) std::unique_lock
Read-write access (multiple readers) std::shared_lock (with std::shared_mutex)

Summary:

  • Use std::mutex for explicit control over locking.
  • Prefer std::lock_guard for simplicity and safety in most cases.
  • Use std::unique_lock for advanced locking scenarios.
  • Use std::shared_lock when you need shared read and exclusive write access.

No comments:

Post a Comment

LeetCode C++ Cheat Sheet June

🎯 Core Patterns & Representative Questions 1. Arrays & Hashing Two Sum – hash map → O(n) Contains Duplicate , Product of A...