一、锁的核心作用
多线程并发访问共享资源时,会出现“竞态条件(race condition)”,如多个线程同时读写同一变量,导致数据混乱,锁的核心作用是实现互斥访问,保证同一时间只有一个线程能操作共享资源,同时通过同步机制实现线程间有序协作,避免数据异常。
解决并发安全问题,保证数据一致性,实现线程间有序协作。
二、底层原始锁
原始锁是所有锁的基础,需手动管理加锁/解锁,通常作为上层自动锁的底层依赖。
1. std::mutex(独占锁)
核心操作:
lock()(阻塞加锁,拿不到锁则一直等待)、unlock()(手动解锁)特点:独占性(同一时间仅一个线程能持有)、非递归(同一线程不能重复加锁)
缺陷:需手动解锁,遗漏解锁会导致死锁;无超时机制,可能永久阻塞
2. 其它原始锁
std::recursive_mutex(递归锁):允许同一线程多次加锁,解锁次数需与加锁次数一致,适用于递归函数、嵌套加锁场景
std::timed_mutex(超时锁):新增
try_lock_for()、try_lock_until()接口,拿不到锁时不会永久阻塞,适用于需超时控制的场景std::shared_mutex(读写锁底层):C++17引入,为读写分离提供基础,支撑读共享、写独占的逻辑
三、RAII 自动锁管理
RAII(资源获取即初始化)机制,通过对象构造/析构自动管理锁的生命周期,彻底解决原始锁手动解锁遗漏、异常死锁的问题。
1. std::lock_guard(最简单自动锁)
核心逻辑:构造函数自动执行
lock(),析构函数自动执行unlock()特点:轻量、高效,不可手动解锁、不可复制、不可移动
适用场景:简单临界区(代码段短,无需中途解锁,仅需保证互斥)
std::lock_guard<std::mutex> lock(mtx);
2. std::unique_lock(最灵活自动锁)
lock_guard 的加强版,兼顾自动管理与灵活操作,是线程同步的核心锁。
基础功能:自动加锁/解锁,支持手动
lock()、unlock()、try_lock()核心特性:支持延迟上锁、锁所有权转移(
std::move()),可配合条件变量使用适用场景:复杂同步场景(需中途解锁、等待唤醒)
std::unique_lock<std::mutex> lock(mtx);
3. std::shared_lock(读写锁自动管理)
配合
std::shared_mutex使用,实现“读共享、写独占”特点:读操作可多线程同时进行,写操作独占,提升高并发读场景的效率
适用场景:读多写少(如配置读取、日志查询)
四、线程同步
锁仅能实现“互斥”,若需线程间有序协作(如等待某个条件成立、唤醒其他线程),需结合条件变量,且仅std::unique_lock可配合使用
1. 核心组件:std::condition_variable(条件变量)
核心作用:实现线程间“等待-唤醒”通信,需与
std::unique_lock配合(唯一支持的锁类型)核心操作:
cv.wait(lock, 谓词):自动解锁、阻塞、重新加锁,防止虚假唤醒cv.notify_one():唤醒一个等待的线程cv.notify_all():唤醒所有等待的线程
适用场景:生产者-消费者、线程池、交替执行等需要协作的场景
2. 同步逻辑总结
互斥锁保证“同一时间仅一个线程操作资源”,同步(条件变量)保证“线程按预期顺序执行”,二者结合构成完整的多线程并发逻辑。
五、锁的使用场景选择
场景描述 | 推荐锁类型 | 核心原因 |
|---|---|---|
简单临界区,无需中途解锁 | std::lock_guard | 轻量高效,自动管理,无多余操作 |
需中途解锁、等待唤醒,或灵活加锁 | std::unique_lock | 支持手动加解锁、延迟上锁,可配合条件变量 |
读多写少,高并发读场景 | std::shared_lock + std::shared_mutex | 读共享提升并发,写独占保证安全 |
递归函数、嵌套加锁 | std::recursive_mutex | 允许同一线程多次加锁,避免递归死锁 |
需超时控制,避免永久阻塞 | std::timed_mutex | 支持超时加锁,防止死锁 |
六、锁的使用铁律
最小临界区原则:仅对操作共享资源的代码段加锁,锁的范围越小、时间越短,并发效率越高
禁止使用裸锁(手动加解锁),优先使用RAII自动锁(lock_guard/unique_lock)
条件变量必须配合std::unique_lock,不可用其他锁类型
避免交叉加锁(如线程A锁mtx1再锁mtx2,线程B锁mtx2再锁mtx1),防止死锁
读多写少场景优先用shared_mutex,提升并发效率
C++锁体系的核心逻辑:原始锁提供底层互斥能力,RAII自动锁简化管理,条件变量实现线程协作,根据场景选择对应锁类型,既保证并发安全,又提升程序效率。