新闻中心

C++如何使用互斥锁(mutex)和锁守卫(lock_guard)?(代码示例)

2025-12-12
浏览次数:
返回列表
std::lock_guard是RAII风格的自动锁管理工具,构造时加锁、析构时自动解锁,确保临界区安全;需配合全局或共享mutex使用,不可手动解锁或尝试加锁,适用简单独占场景。

c++如何使用互斥锁(mutex)和锁守卫(lock_guard)?(代码示例)

在C++多线程编程中,mutex用于保护共享数据不被多个线程同时访问,而lock_guard是RAII风格的自动锁管理工具——它在构造时加锁、析构时自动解锁,避免忘记解锁或异常导致死锁。

基础用法:声明 mutex + lock_guard 管理临界区

最常见场景是多个线程并发修改同一个变量(如计数器),需用 std::mutex 保护,并用 std::lock_guard 确保安全:

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>

int counter = 0;
std::mutex mtx; // 全局互斥锁

void increment() {
    for (int i = 0; i < 100000; ++i) {
        std::lock_guard<std::mutex> lock(mtx); // 构造即加锁
        ++counter; // 临界区:仅此处访问共享变量
        // 析构自动解锁(即使提前 return 或抛异常也安全)
    }
}

int main() {
    std::vector&lt;std::thread> threads;
    for (int i = 0; i < 4; ++i) {
        threads.emplace_back(increment);
    }
    for (auto& t : threads) t.join();
    std::cout << "Final counter: " << counter << "\n"; // 输出 400000
}

注意:lock_guard 不能手动解锁,也不支持尝试加锁

std::lock_guard 是“独占且不可重入”的简单守卫,设计上不提供 unlock()try_lock() 接口。如果需要更灵活控制,应改用 std::unique_lock

  • 不要写 lock.unlock() —— 编译失败,它没这个成员函数
  • 不要期望它能“尝试加锁失败就跳过”,那得用 unique_lock 配合 try_to_lock 标签
  • 它的生命周期必须严格覆盖整个临界区,通常定义在作用域开头

常见错误:把 mutex 当局部变量或跨线程传递

mutex 必须是所有竞争线程都能访问的同一对象(通常是全局、类成员或静态变量):

微软爱写作 微软爱写作

微软出品的免费英文写作/辅助/批改/评分工具

微软爱写作 130 查看详情 微软爱写作
  • ❌ 错误:每个线程创建自己的 mutex —— 完全起不到同步作用
  • ❌ 错误:把 mutex 通过值传递给线程函数 —— 复制后各持一份,互不干扰
  • ✅ 正确:传引用(std::ref(mtx))或直接捕获(lambda 中 [&mtx])或作为全局/成员变量

进阶提示:类内使用 mutex 保护成员变量

封装更安全的方式是把 mutex 和受保护的数据放在一起,只暴露加锁后的操作接口:

class ThreadSafeCounter {
private:
    mutable std::mutex mtx; // mutable 允许 const 成员函数里加锁
    int value = 0;

public:
    void increment() {
        std::lock_guard<std::mutex> lock(mtx);
        ++value;
    }

    int get() const {
        std::lock_guard<std::mutex> lock(mtx);
        return value;
    }
};

这样调用者无需关心锁,也难以误操作;const 成员函数也能安全读取,因为 mutable 允许在 const 函数中修改 mutex。

基本上就这些。用好 lock_guard 的关键是理解 RAII —— 把“加锁”交给构造,“解锁”交给析构,不用操心时机和异常路径。不复杂但容易忽略细节。

以上就是C++如何使用互斥锁(mutex)和锁守卫(lock_guard)?(代码示例)的详细内容,更多请关注其它相关文章!


# 死锁  # 眉山网站seo外包  # 营销推广广告语  # 金华专业小红书推广营销  # 关键词报告中平均排名  # 固始360推广营销  # 广州外包网站怎么推广  # 韩漫画seo  # 网站合并推广  # 泰州优化seo搜索  # 网站SEO优化方法值得关注  # 自己的  # 如何实现  # 工具  # 多个  # 互斥  # 多线程  # 微软  # 解锁  # 如何使用  # 加锁  # 作用域  # stream  # ios  # c++  # ai 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: Win11文件资源管理器卡顿怎么修 Win11重置资源管理器进程优化响应速度【修复方法】  怎样在Excel中做仪表盘_Excel仪表盘设计与关键指标展示方法  Django模型中自动计算可用余额的实现方法  2026年发布! 美少女养成动作RPG《神剑少女战记》发布实机演示  LINUX怎么设置定时任务_LINUX crontab配置教程  凉拌黄瓜怎么拌更入味 凉拌黄瓜简单家常做法  Composer如何解决json扩展缺失的错误  Fabric Mod开发:在1.19.3+版本中正确添加自定义物品并管理物品组  深入理解J*a链表中的IPosition接口与使用  汽水音乐在线解析 汽水音乐在线解析入口  谷歌邮箱注册显示错误Gmail服务器异常与延迟处理  创客贴用户入口官网登录 创客贴网页版电脑版系统  c++中的std::basic_string的SSO优化_c++短字符串优化深度解析  J*aScript对象创建方式_J*aScript设计模式应用  在Blazor WebAssembly应用中动态注入客户端特定指标代码的策略  在VS Code中配置和运行Dart程序的完整步骤  Golang如何处理RPC请求负载均衡_Golang RPC请求负载均衡策略与实践  Lar*el的路由模型绑定怎么用_Lar*el Route Model Binding简化控制器逻辑  印象笔记如何设提醒任务防漏执行_印象笔记设提醒任务防漏执行【任务提醒】  最新韩小圈网页版登录入口_官网在线观看官方链接  解决移动端滚动问题的overflow属性应用指南  React项目中导航栏Logo自适应布局:避免裁剪与布局溢出  Go语言中Map值调用指针接收器方法的限制与应对  Go语言中JSON数据解析与字段访问教程  机构:以往存储涨价周期小米利润率实际上有所改善 能转嫁给消费者等  在Typer应用中优雅地处理和重组任意命令行参数  将JSON对象数组转置为键值对列表的实用指南  Go语言中JSON数据解码与字段访问指南  微博网页版怎么开启两步验证_微博网页版账号安全两步验证设置方法  AO3官方镜像站点汇总 AO3同人作品网页版直达链接  快速CSGO开箱网站指南 CSGO开箱平台推荐  Win10怎么设置静态IP地址 Win10手动配置IP地址步骤【指南】  如何在离线环境中使用Composer_Composer离线安装依赖包的技巧与策略  QQ邮箱官网登录入口 QQ邮箱网页版邮箱快速登录  动漫共和国防屏蔽稳定域名-动漫共和国官方正版直达通道  如何在CSS中使用visited与link控制链接颜色_visited link伪类配合  如何使用Rector自动化升级旧代码_通过Composer安装和配置Rector进行代码重构  MAC如何将整个网页截长图_MAC使用Safari的导出为PDF或第三方工具  俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达  小红书商家版怎样在笔记嵌入商品卡路径_小红书商家版在笔记嵌入商品卡路径【挂载教程】  yandex入口引擎手机版 yandex安卓版下载入口  Spyder启动失败:字体文件权限拒绝错误解决方案  腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程  css元素hover动画延迟生效怎么办_使用animation-delay调整触发时间  必由学官网首页入口 必由学教师网页版登录指南  《北京人工智能产业白皮书(2025)》发布:全年核心产值预计突破 4500 亿元  AO3官方在线访问地址 Archive of Our Own最新镜像合集  绝地鸭卫平a核爆刀流玩法攻略  c++如何实现一个简单的ECS框架_c++数据驱动设计与游戏开发  如何使用 Excel 发布器与 Power BI 分享 Excel 洞察 

搜索