• C++ std::unique_lock 用法介绍



    std::unique_lock 是 C++11 提供的一个用于管理互斥锁的类,它提供了更灵活的锁管理功能,适用于各种多线程场景。

    1.创建 std::unique_lock 对象

    std::unique_lock<std::mutex> lock(mutex); // 创建 std::unique_lock 并关联互斥锁 mutex
    
    • 1

    你可以在构造函数中传入一个互斥锁(std::mutex 或其它互斥锁类型)来创建 std::unique_lock 对象,并且会在构造时获取互斥锁的所有权。此时,互斥锁被锁住,其他线程无法获得锁。

    2.自动加锁和解锁

    {
        std::unique_lock<std::mutex> lock(mutex); // 自动加锁
        // 临界区代码
    } // 自动解锁
    
    • 1
    • 2
    • 3
    • 4

    使用 std::unique_lock 创建的对象,当其生命周期结束时(通常是在大括号的作用域结束时),会自动解锁互斥锁,以确保互斥锁在不再需要时被释放。

    3.延迟加锁与手动加解锁

    std::unique_lock 还支持在初始化时不立即加锁,而是在需要时延迟加锁。这种特性对于一些多线程场景非常有用,允许你在获得锁之前执行一些非临界区的操作,从而减少锁的持有时间。

    创建 std::unique_lock 对象时,传入互斥锁但不加锁:

    std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
    
    • 1

    在需要时手动加锁:

    lock.lock();   // 手动加锁
    // 临界区代码
    lock.unlock(); // 手动解锁
    
    • 1
    • 2
    • 3

    你可以使用 lock() 手动加锁,然后在互斥锁保护的临界区内执行代码,最后使用 unlock() 手动解锁。这种方式可以让你更灵活地控制锁的生命周期。

    4.尝试加锁

    std::unique_lock 还提供了 try_lock() 方法,用于尝试加锁,如果锁不可用,则返回 false,如果锁成功获取,则返回 true。

    std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
    if (lock.try_lock()) {
        // 锁成功获取,执行临界区代码
        lock.unlock();
    } else {
        // 锁不可用,执行其他逻辑
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5.配合条件变量使用

    condition_variable(条件变量)是 C++11 中提供的一种多线程同步机制,它允许一个或多个线程等待另一个线程发出的通知,以便能够有效地进行线程同步。

    条件变量(std::condition_variable)需要与 std::unique_lock 一起使用,以实现线程的等待和通知机制。

    std::unique_lock<std::mutex> lck(mutex);
    while (!condition) {
        conditionVariable.wait(lock); // 等待条件满足并释放锁
    }
    // 条件满足,重新获取锁并继续执行
    
    • 1
    • 2
    • 3
    • 4
    • 5

    条件变量的成员函数 wait() 会在阻塞线程的那一刻(当线程被添加到等待队列中时),函数会自动调用 lck.unlock() 释放锁,允许其他锁定的线程继续执行。

    一旦收到唤醒通知(由其他线程调用 notify_one() 或 notify_all() 通知),该函数就会解除阻塞并调用 lck.lock(),使 lck 处于与调用该函数时相同的状态,然后函数返回。请注意,返回前调用 lck.lock() 加锁可能会再次阻塞线程。

    为什么条件变量需要互斥锁的配合呢?

    因为 condition 和等待队列都是多线程的共享资源,当访问这些共享资源时需要互斥访问。

    6.小结

    std::unique_lock 提供了对互斥锁更高级别的控制和灵活性,使得多线程编程更加安全和容易。在多数情况下,推荐使用 std::unique_lock 而不是直接操作互斥锁,因为它能够自动管理锁的生命周期,减少了出错的机会。


    参考文献

    std::unique_lock - cplusplus.com
    std::condition_variable - cplusplus.com

  • 相关阅读:
    电脑蓝屏怎么办 七大原因及解决办法来帮你
    23种设计模式(十八)迭代器模式(阁瑞钛伦特软件-九耶实训)
    Python学习之路02 之分支结构
    k8s一些难懂的技术点(1)
    SVN:下载、安装和中文设置
    Docker容器内存限制
    USB PD v1.0快速充电通信原理
    LeetCode 1175. 质数排列(质数判断+组合数学)
    大模型日报 2024-06-28
    LeetCode_多源 BFS_中等_2258.逃离火灾
  • 原文地址:https://blog.csdn.net/K346K346/article/details/133132703