当前位置: 代码网 > it编程>编程语言>C/C++ > C++中锁的种类与使用实例详解

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

2026年05月11日 C/C++ 我要评论
关于c++中锁的种类与使用optimized tool selectionc++ 标准库中有多种锁管理机制,各有不同的特性和适用场景:看这段代码中使用的是 std::lock_guard,这是一个自动

关于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++锁的种类与使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com