mutex


Header: <mutex>

The <mutex> header, introduced in C++11, provides synchronization primitives for multi-threaded programming. It offers various types of mutexes and lock classes to help manage concurrent access to shared resources, preventing data races and ensuring thread safety.

Key Characteristics

Example 1: Basic Mutex Usage

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>

std::mutex mtx;
int shared_value = 0;

void increment(int id) {
    for (int i = 0; i < 1000; ++i) {
        mtx.lock();
        ++shared_value;
        mtx.unlock();
    }
    std::cout << "Thread " << id << " finished.\n";
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < 10; ++i) {
        threads.emplace_back(increment, i);
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "Final value: " << shared_value << std::endl;
    return 0;
}

Explanation

Example 2: Using std::lock_guard for RAII-style Locking

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>

std::mutex mtx;
int shared_value = 0;

void increment(int id) {
    for (int i = 0; i < 1000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        ++shared_value;
    }
    std::cout << "Thread " << id << " finished.\n";
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < 10; ++i) {
        threads.emplace_back(increment, i);
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "Final value: " << shared_value << std::endl;
    return 0;
}

Explanation

Example 3: Using std::unique_lock with Deferred Locking

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

std::mutex mtx;
int shared_resource = 0;

void worker(int id) {
    std::unique_lock<std::mutex> lock(mtx, std::defer_lock);

    // Simulate some work before locking
    std::this_thread::sleep_for(std::chrono::milliseconds(id * 100));

    lock.lock();
    shared_resource += id;
    std::cout << "Thread " << id << " added " << id << ". New value: " << shared_resource << std::endl;
    lock.unlock();

    // Simulate more work after unlocking
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    lock.lock();
    shared_resource *= 2;
    std::cout << "Thread " << id << " doubled. New value: " << shared_resource << std::endl;
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 1; i <= 5; ++i) {
        threads.emplace_back(worker, i);
    }

    for (auto& t : threads) {
        t.join();
    }

    return 0;
}

Explanation

Example 4: Using std::timed_mutex for Timed Lock Attempts

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

std::timed_mutex resource_mutex;

void worker(int id) {
    for (int i = 0; i < 3; ++i) {
        if (resource_mutex.try_lock_for(std::chrono::milliseconds(200))) {
            std::cout << "Thread " << id << " acquired lock.\n";
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            resource_mutex.unlock();
        } else {
            std::cout << "Thread " << id << " couldn't acquire lock.\n";
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < 4; ++i) {
        threads.emplace_back(worker, i);
    }

    for (auto& t : threads) {
        t.join();
    }

    return 0;
}

Explanation

Additional Considerations

Summary

The <mutex> header in C++ provides essential tools for synchronization in multi-threaded programs. It offers various mutex types and lock classes to help manage concurrent access to shared resources safely and efficiently.

Key points to remember: 1. Use std::mutex for basic mutual exclusion 2. Prefer RAII-style locks like std::lock_guard and std::unique_lock for exception safety 3. std::unique_lock offers more flexibility with deferred and timed locking 4. std::timed_mutex allows for timed lock attempts 5. Always be mindful of potential deadlocks and performance implications when using mutexes

By effectively using the synchronization primitives provided by <mutex>, C++ developers can write thread-safe code, manage shared resources, and build robust multi-threaded applications while minimizing the risks of data races and deadlocks.

Previous Page | Course Schedule | Course Content