互斥锁管理之lock_guard和scope_lock学习 前面博客在多线程中处理访问共享资源使用mutex的lock和unlock来对数据进行保护避免数据据竞争。如果对某一段功能代码进行保护每次都要lock和unlock如果忘记unlock了那么多线程访问就卡着永远不会结束了本篇记录一种简便的方法来进行数据保护即lock_guard和scope_lock。先看之前的mutex的示例//lock_guard.cpp lock_guard example //#include iostream // std::cout #include thread // std::thread #include mutex // std::mutex //临界区互斥锁 std::mutex mtx; // mutex for critical section int g_count 0; //自增函数测试 void incrementation() { printf(incrementationstart lock\n); mtx.lock(); for (int i 0; i 1000000; i) { g_count; } //模拟耗时 std::this_thread::sleep_for(std::chrono::seconds(1)); //休眠1秒 printf(incrementationend lock\n); mtx.unlock(); } int main() { std::thread t1(incrementation); std::thread t2(incrementation); t1.join(); t2.join(); //理论应该 2000000不加锁实际永远小于这个数 printf(g_count%d\n, g_count); printf(hello learn mutex\n); return 0; }编译运行如果忘记unlock()了那这个程序就永远不会结束了。1.lock_guard现在把它改成std::lock_guardstd::mutex lock(mtx);一行代码就解决这种问题。//lock_guard.cpp lock_guard example //#include iostream // std::cout #include thread // std::thread #include mutex // std::mutex //临界区互斥锁 std::mutex mtx; // mutex for critical section int g_count 0; //自增函数测试 void incrementation() { printf(incrementationstart lock\n); std::lock_guardstd::mutex lock(mtx); for (int i 0; i 1000000; i) { g_count; } //模拟耗时 std::this_thread::sleep_for(std::chrono::seconds(1)); //休眠1秒 printf(incrementationend lock\n); } int main() { std::thread t1(incrementation); std::thread t2(incrementation); t1.join(); t2.join(); //理论应该 2000000不加锁实际永远小于这个数 printf(g_count%d\n, g_count); printf(hello learn lock_guard\n); return 0; }编译运行运行结果是一样的。lock_guard 是互斥体包装器为在作用域块期间占有互斥体提供便利的 RAII 风格机制。当创建lock_guard 对象时它尝试接收给定互斥体的所有权。当控制离开创建 lock_guard 对象的作用域时销毁 lock_guard 并释放互斥体。2.scope_lock上面介绍的是只有一个互斥体如果有两个互斥体呢lock_guard要写两次例如一个银行转帐系统转帐时既要锁住转出账户也要锁入转入账户不然同时操作就乱了。//scoped_lock.cpp scoped_lock example #include iostream #include thread #include mutex #include vector #include chrono #include memory // 如果需要智能指针 class BankAccount { private: int balance_; mutable std::mutex mtx_; // 加 mutable允许在 const 函数中修改 public: explicit BankAccount(int initial) : balance_(initial) {} void transfer(BankAccount target, int amount) { // 错误示例不要这样写可能死锁 // std::lock_guardstd::mutex lock1(mtx_); // 假设先锁 from // std::lock_guardstd::mutex lock2(target.mtx_); // 再锁 target // 如果另一个线程先锁 target 再锁 from就会死锁 // 正确的 lock_guard 写法需要配合 std::lock std::lock(mtx_, target.mtx_); // 先统一锁定 std::lock_guardstd::mutex lock1(mtx_, std::adopt_lock); // 接管已锁 std::lock_guardstd::mutex lock2(target.mtx_, std::adopt_lock); if (balance_ amount) { balance_ - amount; target.balance_ amount; std::cout [成功] 转账 amount 当前账户余额: balance_ std::endl; } else { std::cout [失败] 余额不足当前余额: balance_ std::endl; } } int getBalance() const { std::lock_guardstd::mutex lock(mtx_); return balance_; } }; int main() { BankAccount accountA(1000); BankAccount accountB(500); std::vectorstd::thread threads; // 线程1A - B 转账 200执行3次 threads.emplace_back([]() { for (int i 0; i 3; i) { accountA.transfer(accountB, 200); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }); // 线程2B - A 转账 100执行3次 threads.emplace_back([]() { for (int i 0; i 3; i) { accountB.transfer(accountA, 100); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }); // 线程3A - B 转账 300执行2次 threads.emplace_back([]() { for (int i 0; i 2; i) { accountA.transfer(accountB, 300); std::this_thread::sleep_for(std::chrono::milliseconds(15)); } }); for (auto t : threads) { t.join(); } std::cout \n 最终余额 std::endl; std::cout 账户A: accountA.getBalance() std::endl; std::cout 账户B: accountB.getBalance() std::endl; printf(hello learn lock_guard\n); return 0; }编译运行如果是更多个数据项要保护那么又得加多个互斥体这样既窗容易出错也很难维护那边有没有更好的方法呢答案就是用scoped_lock解决这个问题可以同时多个互斥体这是c17的标准。//scoped_lock.cpp scoped_lock example #include iostream #include thread #include mutex #include vector #include chrono #include memory // 如果需要智能指针 class BankAccount { private: int balance_; mutable std::mutex mtx_; // 加 mutable允许在 const 函数中修改 public: explicit BankAccount(int initial) : balance_(initial) {} void transfer(BankAccount target, int amount) { // 使用 std::scoped_lock 同时锁定两个互斥量 std::scoped_lock lock(mtx_, target.mtx_); if (balance_ amount) { balance_ - amount; target.balance_ amount; std::cout [成功] 转账 amount 当前账户余额: balance_ std::endl; } else { std::cout [失败] 余额不足当前余额: balance_ std::endl; } } int getBalance() const { std::lock_guardstd::mutex lock(mtx_); return balance_; } }; int main() { BankAccount accountA(1000); BankAccount accountB(500); std::vectorstd::thread threads; // 线程1A - B 转账 200执行3次 threads.emplace_back([]() { for (int i 0; i 3; i) { accountA.transfer(accountB, 200); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }); // 线程2B - A 转账 100执行3次 threads.emplace_back([]() { for (int i 0; i 3; i) { accountB.transfer(accountA, 100); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }); // 线程3A - B 转账 300执行2次 threads.emplace_back([]() { for (int i 0; i 2; i) { accountA.transfer(accountB, 300); std::this_thread::sleep_for(std::chrono::milliseconds(15)); } }); for (auto t : threads) { t.join(); } std::cout \n 最终余额 std::endl; std::cout 账户A: accountA.getBalance() std::endl; std::cout 账户B: accountB.getBalance() std::endl; printf(hello learn lock_guard\n); return 0; }编译运行参考https://cplusplus.com/reference/mutex/lock_guard/https://zh.cppreference.com/cpp/thread/lock_guardhttps://zh.cppreference.com/cpp/thread/scoped_lock

相关新闻

最新新闻

UE6 vs Unity 7:下一代引擎选型与迁移成本全解析

UE6 vs Unity 7:下一代引擎选型与迁移成本全解析

看到“UE6 vs Unity 7”这个标题,先别急着站队。 Unreal Engine 6 和 Unity 7 目前都没有正式对外发布,网上大量对比内容更多是基于现有版本生态的推演。这篇文章不是来争论“谁更强”的,而是把两个方向放到同一张桌子上:它们各自…

2026/9/1 18:27:20
古籍文档图像识别与分析:检测识别版面排序全流程实现

古籍文档图像识别与分析:检测识别版面排序全流程实现

简介:本资源为粤港澳大湾区(黄埔)国际算法算例大赛中‘古籍文档图像识别与分析’赛题的Alphx队完整参赛源码包,面向AI竞赛选手、计算机视觉与古籍数字化方向的研究者及工程实践者,聚焦OCR增强、版面分析、古文语义理解…

2026/9/1 18:27:20
OpenCV+C++遥感图像配准系统实战解析

OpenCV+C++遥感图像配准系统实战解析

简介:本资源是一套基于OpenCV与C实现的遥感图像配准系统完整工程,面向计算机视觉初学者、遥感图像处理学习者及图像算法实践者,解决多源遥感图像几何对齐这一典型任务。压缩包共47个文件,含16个头文件(.h)定…

2026/9/1 18:27:20
基于FastAPI+Vue3+微信小程序的网约车毕业设计实战

基于FastAPI+Vue3+微信小程序的网约车毕业设计实战

每年到毕业设计选题季,总有一批同学会在“图书管理系统”“购物商城”“博客系统”这几个经典题目之间反复横跳。不是说这些题目不能做,而是它们已经在太多届学长学姐的论文和答辩PPT里出现过,老师一眼就能看出套路,很难给出高分。…

2026/9/1 18:27:20
H3节点优化提示词:根治本地大模型“开头破音”难题

H3节点优化提示词:根治本地大模型“开头破音”难题

最近在折腾本地大模型应用时,我遇到了一个挺典型的问题:费劲部署好一个模型,写好了提示词,结果生成的文本开头总带着奇怪的“破音”或前言不搭后语的“废话”。这就像你精心准备了一份演讲稿,结果一开口先打了个嗝&…

2026/9/1 18:27:20
电池箱体焊完就漏水?长焊缝气密三道关

电池箱体焊完就漏水?长焊缝气密三道关

这篇文章讲的是:新能源汽车电池箱体(下壳体/托盘)要求 IP67 起步——1米水深浸泡30分钟不能进水,高端车型要求 IP68。难点在于一个长度 1.5-2 米的箱体,焊缝总长可达数十米,要求全程气密、整体变形控制在装…

2026/9/1 18:22:19