理解 lock_guard, unique_lock 与 shared_lock 的设计哲学与应用场景

一. lock_guard

lock_guard 比较简单,利用RAII 方式,构造时加锁,析构时解锁

cpp 复制代码
template <class Mutex>
class lock_guard {
    Mutex& mutex_;
public:
    // 构造时加锁
    explicit lock_guard(Mutex& m) : mutex_(m) { mutex_.lock(); }

    // 支持adopt_lock:接管已经加过锁的mutex
    lock_guard(Mutex& m, std::adopt_lock_t) : mutex_(m) { }

    // 析构时解锁
    ~lock_guard() { mutex_.unlock(); }

    // 禁止拷贝(移动操作因存在用户声明的拷贝操作而不会被隐式生成)
    lock_guard(const lock_guard&) = delete;
    lock_guard& operator=(const lock_guard&) = delete;
};

这里的adopt_lock_t,比较简单,顾名思义领养一个孩子,不是你生的(加锁),但领养后需要照顾(解锁)

cpp 复制代码
std::mutex mtx;
int shared_data = 0;

void test() {
    std::lock_guard<std::mutex> lock(mtx);  
    ++shared_data;
}

二.unique_lock

cpp 复制代码
template <class Mutex>
class unique_lock {
    Mutex* mutex_;
    bool owns_;     // 是否持有锁
public:
    // 默认构造:不关联任何mutex
    unique_lock() noexcept : mutex_(nullptr), owns_(false) {}

    // 普通构造:立即加锁(注意owns_先设为false,lock成功后才设true,保证异常安全)
    explicit unique_lock(Mutex& m) : mutex_(&m), owns_(false) {
        mutex_->lock();
        owns_ = true;
    }

    // 延迟加锁:不立即加锁
    unique_lock(Mutex& m, std::defer_lock_t) : mutex_(&m), owns_(false) {}

    // 尝试加锁:非阻塞
    unique_lock(Mutex& m, std::try_to_lock_t)
        : mutex_(&m), owns_(m.try_lock()) {}

    // 接管已加锁的mutex
    unique_lock(Mutex& m, std::adopt_lock_t) : mutex_(&m), owns_(true) {}

    // 支持移动
    unique_lock(unique_lock&& other) noexcept;
    unique_lock& operator=(unique_lock&& other) noexcept;

    // 手动控制
    void lock();
    void unlock();
    bool try_lock();

    // 析构时:如果持有锁,解锁
    ~unique_lock() { if (owns_) mutex_->unlock(); }
};

跟lock_guard比,unique_lock最核心的区别就三个。

**一是能手动unlock/lock。**你可以在锁的生命周期中间释放锁、做一些不需要锁保护的操作、然后再重新加锁。这对控制锁的粒度至关重要,尤其是在锁保护区域内有耗时操作但这个操作本身不需要锁保护的场景下。

二是支持延迟加锁和try_lock。 defer_lock让你先构造unique_lock对象但不立即加锁,等后面你自己决定什么时候调lock()try_to_lock尝试加锁但不阻塞,加不上就返回false让你自己处理。这两个能力lock_guard完全没有。

**三是支持移动语义。**unique_lock可以从一个作用域移动到另一个作用域,锁的所有权跟着走。lock_guard既不能拷贝也不能移动,锁死在创建它的那个作用域。

三.shared_lock

cpp 复制代码
std::shared_mutex rw_mtx;
std::map<std::string, int> cache;

// 读操作:加共享锁,多个读线程可以并发
int read_cache(const std::string& key) {
    std::shared_lock lock(rw_mtx);  // 共享锁(读锁)
    auto it = cache.find(key);
    return it != cache.end() ? it->second : -1;
}

// 写操作:加独占锁,写的时候不允许任何读或写
void write_cache(const std::string& key, int value) {
    std::unique_lock lock(rw_mtx);  // 独占锁(写锁)
    cache[key] = value;
}

与unique_lock的区别

最大的区别是,对于的管理的对象,不会进行独占,其他的线程通过shared_lock也可以共同的管理共享互斥量(shared_mutex);

相关推荐
2zcode1 分钟前
基于低光照增强与轻量型CNN道路实时识别算法研究(UI界面+数据集+训练代码)
人工智能·算法·cnn·低光照增强·自动驾驶技术
郝学胜-神的一滴16 分钟前
跨平台动态库与头文件:从原理到命名的深度解析
linux·c++·程序人生·unix·cmake
代码中介商16 分钟前
C++ 仿函数(Functor)深度解析:从基础到应用
开发语言·c++
小雅痞23 分钟前
[Java][Leetcode middle] 209. 长度最小的子数组
java·算法·leetcode
王老师青少年编程25 分钟前
csp信奥赛C++高频考点专项训练之字符串 --【字符串基础】:[NOIP 2018 普及组] 标题统计
c++·字符串·csp·高频考点·信奥赛·专项训练·标题统计
小杍随笔31 分钟前
Rust桌面GUI框架:性能优化与实战避坑指南
开发语言·性能优化·rust
二哈赛车手34 分钟前
新人笔记---项目中简易版的RAG检索后评测指标(@Recall ,Mrr..)实现
java·开发语言·笔记·spring·ai
做时间的朋友。34 分钟前
精准核酸检测
java·数据结构·算法
格林威36 分钟前
3D相机视觉检测:环境光太强,结构光点云全是噪点怎么办?
开发语言·人工智能·数码相机·计算机视觉·3d·视觉检测·工业相机
Rust语言中文社区43 分钟前
【Rust日报】2026-05-02 Temper - 用 Rust 编写的 Minecraft 服务器项目发布 0.1.0 版
运维·服务器·开发语言·后端·rust