C++中锁的种类与使用实例详解

 更新时间:2026年05月11日 10:51:28   作者:LHL000125  
本文介绍了C++标准库中的多种锁管理机制,重点讲解了各种锁的特点、适用场景及使用方法,并提供了代码示例,最后总结了一些使用技巧和避坑指南,感兴趣的朋友一起看看吧

关于c++中锁的种类与使用

Optimized tool selectionC++ 标准库中有多种锁管理机制,各有不同的特性和适用场景:
看这段代码中使用的是 std::lock_guard,这是一个自动管理锁的工具。锁会在以下时刻释放:

锁的生命周期

.....
static std::mutex g_mutex;           // 保护 g_control / g_reply 的并发访问
.....
void handleControlGram(const ControlGram &cg) {
    std::lock_guard<std::mutex> lk(g_mutex);  // ← 获取锁
    g_control.SteeringThrottle = (uint8_t)cg.SteeringThrottle;
    // ... 其他赋值操作
    g_control.ControlMode = cg.ControlMode;
}  // ← 函数结束时,lk 对象析构,锁自动释放

锁的释放时机

  • 函数返回时lock_guard 对象超出作用域,析构函数被调用,锁自动释放
  • 无需手动调用 unlock()

为什么使用 lock_guard?

这是 RAII 模式(Resource Acquisition Is Initialization)的应用:

情形手动 lock/unlocklock_guard
正常执行✓ 释放✓ 自动释放
异常抛出锁泄露✓ 析构仍会释放
逻辑分支✗ 容易遗漏✓ 自动保证

在 C++ 中,是解决多线程数据竞争的核心工具(C++11 及以后标准提供了完善的锁机制)。针对你的 NVIDIA Orin(Ubuntu20.04,ARM 架构),所有标准 C++ 锁都可以直接使用,编译时仅需链接线程库(-pthread)。

我会分 底层互斥体(锁本体)RAII 自动锁管理工具(推荐必用) 两部分讲解,包含种类、特性、区别、使用场景、代码示例,最后给避坑指南。

一、前置核心知识

  1. 作用:保护共享资源(变量、文件、硬件接口),保证同一时间只有一个/指定线程访问,避免数据错乱。
  2. 核心头文件
    #include <mutex>        // C++11 基础锁
    #include <shared_mutex> // C++17 读写锁
    #include <thread>       // 线程
    
  3. 黄金原则永远用 RAII 自动管理锁,不要手动 lock()/unlock()(极易忘记解锁导致死锁)。
  4. 编译命令(Orin 通用):
    g++ -std=c++17 代码.cpp -o 程序 -pthread
    

二、第一部分:C++ 标准底层互斥体(锁的本体)

这是锁的核心实现,分为 独占锁、递归锁、超时锁、读写锁 4 大类,共 5 种:

互斥体类型独占性递归超时共享读写C++ 版本核心特性
std::mutex✅ 独占C++11最基础、性能最高
std::recursive_mutex✅ 独占C++11同一线程可重复加锁
std::timed_mutex✅ 独占C++11可尝试加锁,超时放弃
std::recursive_timed_mutex✅ 独占C++11递归+超时
std::shared_mutex✅ 独占✅ 读写分离C++17读共享、写独占

1.std::mutex(基础独占锁)

  • 特性独占排他锁,同一时间只能被一个线程持有;不可递归、不可超时、不可共享
  • 适用场景:90% 的常规多线程场景(简单共享变量保护)。
  • 禁止操作:同一个线程不能加锁两次(直接死锁)。

2.std::recursive_mutex(递归独占锁)

  • 特性:允许同一个线程多次加锁,必须解锁相同次数才会释放;其他特性同 mutex
  • 适用场景递归函数、嵌套调用中需要加锁的场景(极少用,能不用就不用)。

3.std::timed_mutex(超时独占锁)

  • 特性:支持超时尝试加锁,不会永久阻塞线程。
  • APItry_lock_for(时间)try_lock_until(时间点)
  • 适用场景:需要避免永久死等锁的场景(如硬件通信、超时任务)。

4.std::shared_mutex(读写锁 / 共享互斥锁,C++17)

  • 核心特性读写分离
    • 读模式(共享):多个线程可以同时加锁读数据;
    • 写模式(独占):只有一个线程能加锁写数据,写时禁止读。
  • 适用场景读多写少(如配置读取、日志、缓存),性能远高于普通独占锁。

三、第二部分:RAII自动锁管理工具(必用!)

直接操作底层互斥体容易忘记解锁,C++ 提供了 4 种自动锁工具,构造时加锁,析构时自动解锁

管理工具配合锁类型手动解锁超时支持多锁同时加锁核心用途
std::lock_guard所有独占锁最简单、最常用(默认首选)
std::unique_lock所有独占锁灵活锁(配合条件变量、手动控制)
std::shared_lockshared_mutex读写锁的读模式(共享)
std::scoped_lock所有锁C++17 同时锁多个锁,防死锁

四、完整使用示例(可直接在 Orin 上运行)

示例 1:基础用法std::mutex + lock_guard(首选)

最常用,保护简单共享变量:

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
mutex mtx;           // 全局互斥锁
int share_num = 0;   // 共享资源
void add_num() {
    // 构造自动加锁,离开作用域自动解锁
    lock_guard<mutex> lock(mtx); 
    share_num++;
    cout << "线程ID: " << this_thread::get_id() << " 数值: " << share_num << endl;
}
int main() {
    thread t1(add_num);
    thread t2(add_num);
    t1.join();
    t2.join();
    return 0;
}

示例 2:递归锁recursive_mutex

解决递归函数加锁问题:

#include <mutex>
recursive_mutex rmtx;
void func(int n) {
    lock_guard<recursive_mutex> lock(rmtx);
    if (n > 0) func(n-1); // 同一线程重复加锁,无死锁
}

示例 3:超时锁timed_mutex + unique_lock

避免永久阻塞:

#include <mutex>
#include <chrono>
timed_mutex tmtx;
void try_lock_func() {
    // 尝试加锁,最多等待 100ms
    unique_lock<timed_mutex> lock(tmtx, chrono::milliseconds(100));
    if (lock.owns_lock()) {
        cout << "加锁成功" << endl;
    } else {
        cout << "加锁超时" << endl;
    }
}

示例 4:读写锁shared_mutex(读多写少最优)

#include <shared_mutex>
shared_mutex s_mtx;
int data = 0;
// 读线程:共享加锁,多个线程可同时读
void read_data() {
    shared_lock<shared_mutex> lock(s_mtx); 
    cout << "读取数据: " << data << endl;
}
// 写线程:独占加锁,同一时间只能一个写
void write_data(int val) {
    unique_lock<shared_mutex> lock(s_mtx); 
    data = val;
    cout << "写入数据: " << data << endl;
}

示例 5:多锁防死锁scoped_lock(C++17)

同时加多个锁,避免死锁:

mutex m1, m2;
void safe_lock() {
    // 一次性加锁 m1 和 m2,自动避免死锁
    scoped_lock lock(m1, m2); 
}

五、关键区别与选型指南(核心总结)

1. 独占锁 vs 读写锁

  • 独占锁(mutex):读写都互斥,适合读写频率差不多的场景;
  • 读写锁(shared_mutex):读不互斥、写互斥,适合读多写少(性能提升 5~10 倍)。

2. lock_guard vs unique_lock

  • lock_guard:轻量、无额外开销,日常开发首选
  • unique_lock:灵活(可手动解锁、超时、配合条件变量),有微小开销。

3. 普通锁 vs 递归锁

  • 99% 的场景不要用递归锁,它会掩盖代码设计问题,仅用于递归函数。

六、避坑指南(Orin 开发必看)

  1. 绝对不要手动调用 lock()/unlock()
    异常、提前 return 都会导致锁无法释放,直接死锁。
  2. 锁粒度尽可能小
    只保护共享资源,不要在锁内执行耗时操作(如网络、打印)。
  3. 避免死锁
    • 多锁必须用 scoped_lock 同时加锁;
    • 不要循环等待锁。
  4. ARM 平台(Orin)优化建议
    短临界区(几行代码)优先用 自旋锁std::spin_lock C++20),避免线程切换开销。

七、快速选型口诀

  1. 常规场景 → mutex + lock_guard
  2. 读多写少 → shared_mutex + shared_lock
  3. 需要灵活控制/条件变量 → unique_lock
  4. 多锁防死锁 → scoped_lock
  5. 递归调用 → recursive_mutex
  6. 不想永久等待 → timed_mutex

总结

  1. C++ 锁分底层互斥体(5种)和 RAII 管理工具(4种),永远用 RAII 自动管理
  2. 基础开发用 std::mutex + std::lock_guard 足够;
  3. 读多写少用读写锁,性能最优;
  4. Orin(ARM)编译加 -std=c++17 -pthread,代码全平台通用。

到此这篇关于关于c++中锁的种类与使用的文章就介绍到这了,更多相关c++锁的种类与使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言和go语言之间的交互操作方法

    C语言和go语言之间的交互操作方法

    下面小编就为大家带来一篇C语言和go语言之间的交互操作方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • C语言每日练习之冒泡排序

    C语言每日练习之冒泡排序

    这篇文章主要介绍了C语言冒泡排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-11-11
  • C语言程序设计之指针的应用详解

    C语言程序设计之指针的应用详解

    为了让大家能够更准确的了解C语言中指针的使用,本文为大家准备了四个指针相关的例题,文中的示例代码讲解详细,感兴趣的小伙伴可以学习一下
    2022-11-11
  • C++面试八股文之如何避免死锁详解

    C++面试八股文之如何避免死锁详解

    在C++中,锁(Lock)是一种同步工具,用于保护共享资源,防止多个线程同时访问,那么如何避免死锁的情况出现呢,下面就为大家简单讲讲
    2023-07-07
  • Visual Studio 2022无法打开源文件的解决方式

    Visual Studio 2022无法打开源文件的解决方式

    这篇文章主要介绍了Visual Studio 2022无法打开源文件的解决方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • Qt实现TCP客户端和服务器通讯程序

    Qt实现TCP客户端和服务器通讯程序

    这篇文章主要为大家详细介绍了Qt实现TCP客户端和服务器通讯程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言:自定义类型详解

    C语言:自定义类型详解

    这篇文章主要介绍了C语言自定义函数详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-09-09
  • opencv3/C++ 离散余弦变换DCT方式

    opencv3/C++ 离散余弦变换DCT方式

    今天小编就为大家分享一篇opencv3/C++ 离散余弦变换DCT方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • 基于malloc与free函数的实现代码及分析

    基于malloc与free函数的实现代码及分析

    本篇文章介绍了malloc与free函数的实现代码及分析。需要的朋友参考下
    2013-05-05
  • C语言版飞机大战游戏

    C语言版飞机大战游戏

    这篇文章主要为大家详细介绍了C语言版飞机大战游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12

最新评论