0%

扩展std::queue——阻塞队列与无穷队列

C++中的锁

互斥锁

mutex(mutual exclusion)是C++中一种用于保证资源在某一时刻只有一个线程访问的同步原语(synchronization primitive)。这用于避免竞态条件(race conditions)并保证共享数据的线程安全访问。

一个最基本的使用互斥锁std::mutex进行线程互斥访问的例子:

  1. 引入相关头文件
    #include <iostream>
    #include <thread>
    #include <mutex>
  2. 定义互斥锁,用于保障共享资源的互斥访问
    std::mutex mtx;
    int shared_counter = 0; // Shared data
  3. 定义函数incrementCounter多次增加共享资源计数
    void incrementCounter(int times) {
    for (int i = 0; i < times; i++) {
    mtx.lock(); // Acquire the lock
    shared_counter++; // Safely access the shared data
    mtx.unlock(); // Release the lock
    std::this_thread::sleep_for(std::chrono::milliseconds(1)); // Sleep for a while (optional)
    }
    }
  1. 创建多个线程并发修改共享资源计数
    int main() {
    const int num_threads = 5;
    const int increments_per_thread = 10;

    std::thread threads[num_threads];

    // Launch the threads
    for (int i = 0; i < num_threads; i++) {
    threads[i] = std::thread(incrementCounter, increments_per_thread);
    }

    // Join the threads
    for (int i = 0; i < num_threads; i++) {
    threads[i].join();
    }

    std::cout << "Final value of shared_counter: " << shared_counter << std::endl;

    return 0;
    }
    结果输出为50,每个线程都正确的执行了共享资源的自增。如果去掉互斥锁,则结果可能会小于50。

上述第三步中mtx.lock()mtx.unlock()构成了一段临界区(critical section),其间的操作是线程安全的。对于声明临界区一般选择避免直接操作mutex,而是使用基于RAII(Resource Acquisition Is Initialization)的写法:

  1. std::unique_lock<std::mutex> lock(mtx)用于基于持有一个std::mutex对象创建一个lock对象并在构造方法中调用mtx.lock()来实现加锁。可以通过调用lock.unlock()来显式调用mtx.unlock()来释放锁,也可在lock对象析构时自动调用mtx.unlock()释放资源,从而可以让锁的作用域更加清晰并避免了编码人员忘记释放资源而造成死锁。所以应尽量避免直接调用std::mutex对象的方法而推荐用std::unique_lock<std::mutex>进行锁的申请与释放。例:

    void incrementCounter(int times) {
    for (int i = 0; i < times; i++) {
    std::unique_lock<std::mutex> lock(mtx); // Acquire the lock
    shared_counter++; // Safely access the shared data
    mtx.unlock(); // Release the lock
    std::this_thread::sleep_for(std::chrono::milliseconds(1)); // Sleep for a while (optional)
    }
    }
  2. std::lock_guard<std::mutex> lock(mtx)std::unique_lock<std::mutex>类似,差别是std::unique_lock<std::mutex>更严格:不提供主动unlock()的接口,只能在构造时加锁,析构时释放锁。例:

    void incrementCounter(int times) {
    for (int i = 0; i < times; i++) {
    std::lock_guard<std::mutex> lock(mtx); // Acquire the lock
    shared_counter++; // Safely access the shared data
    std::this_thread::sleep_for(std::chrono::milliseconds(1)); // Sleep for a while (optional)
    // Release the lock here automatically
    }
    }

阻塞队列

条件变量

无穷队列

成员序列化/反序列化

Disqus评论区没有正常加载,请使用科学上网