news 2026/9/1 1:23:02

互斥锁管理之unique_lock学习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
互斥锁管理之unique_lock学习

前面学习了std::lock_guard和std::scoped_lock,lock_guard的功能是自动解锁,能有效避免忘记unlock()的情况。但只能锁定一个互斥锁,scoped_lock比lock_guard高级,可以同时锁定多个互斥体。而unique_lock比它们更灵活。它‌独占管理互斥量所有权‌,析构时自动解锁(仅当持有锁时),且‌不可复制但可移动‌,支持延迟加锁、手动解锁/加锁、尝试加锁、超时加锁及所有权转移,是唯一能与 std::condition_variable 配合使用的锁包装器。

下面来看它的使用:

//unique_lock.cpp unique_lock 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("incrementation========================>start lock\n"); //std::lock_guard<std::mutex> lock(mtx); std::unique_lock<std::mutex> lock(mtx); for (int i = 0; i < 1000000; ++i) { g_count++; } //模拟耗时 std::this_thread::sleep_for(std::chrono::seconds(1)); //休眠1秒 printf("incrementation========================>end 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 unique_lock\n"); return 0; }

编译运行:

这个例子说明unique_lock具有和lock_guard一样的功能。

unique_lock也可以同时锁定多个互斥体,功能与scoped_lock一样。

std::scoped_lock vs std::unique_lock 详细对比

下面来看锁定两个互斥体的示例

//unique_lock2.cpp unique_lock example //#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex struct Box { explicit Box(int num) : num_things{ num } {} int num_things; std::mutex m; }; void transfer(Box& from, Box& to, int num) { // 仍未实际取锁 std::unique_lock lock1{ from.m, std::defer_lock }; std::unique_lock lock2{ to.m, std::defer_lock }; // 在不死锁的情况下锁定两个 unique_lock std::lock(lock1, lock2); from.num_things -= num; to.num_things += num; // 互斥体 “from.m” 和 “to.m” 会在 unique_lock 析构函数中解锁 } int main() { Box acc1(100); Box acc2(50); std::thread t1(transfer, std::ref(acc1), std::ref(acc2), 10); std::thread t2(transfer, std::ref(acc2), std::ref(acc1), 5); t1.join(); t2.join(); printf("acc1: %d\n", acc1.num_things); printf("acc2: %d\n", acc2.num_things); printf("hello learn unique_lock\n"); return 0; }

编译运行:

unique_lock不仅可以自动析构时解锁,还可以随时unlock()/lock(),例如:

//unique_lock3.cpp unique_lock example随时 unlock() / lock() //#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex #include <vector> int main() { int counter = 0; std::mutex counter_mutex; std::vector<std::thread> threads; //1.记录开始时间点 auto start = std::chrono::steady_clock::now(); auto worker_task = [&](int id) { std::unique_lock<std::mutex> lock(counter_mutex); //锁定 ++counter; printf("%d , 内部计数器: %d\n", id, counter); lock.unlock(); //解锁 // 我们模拟昂贵操作时不保有锁 std::this_thread::sleep_for(std::chrono::seconds(1)); lock.lock(); //锁定 ++counter; printf("%d , 最终计数器: %d\n", id, counter); //离开作用域自动解锁 }; for (int i = 0; i < 10; ++i) threads.emplace_back(worker_task, i); for (auto& thread : threads) thread.join(); //2.记录结束时间点 auto end = std::chrono::steady_clock::now(); //3.计算时间差 auto elapsed = end - start; printf("耗时: %lld 纳秒\n", std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count()); printf("耗时: %lld 微秒\n", std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()); printf("耗时: %lld 毫秒\n", std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()); printf("耗时: %lld 秒\n", std::chrono::duration_cast<std::chrono::seconds>(elapsed).count()); printf("hello learn unique_lock\n"); return 0; } //system_clock vs steady_clock //测量耗时请务必使用 steady_clock,它保证只向前走,不会被系统时间修改(如NTP校时)影响。 //不要用 system_clock 测耗时,因为用户或系统可能修改系统时间,导致测出负数或巨大偏差。system_clock 更适合用来获取日历时间(显示给用户看)

编译运行:

注释掉

第20行 : lock.unlock(); //解锁

第25行:lock.lock(); //锁定

再次编译运行:

说明unique_lock功能更强。

参考:

https://zh.cppreference.com/cpp/thread/unique_lock

【C++】std::unique_lock 详解:灵活的RAII锁管理工具_std::unique+lock-CSDN博客

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 1:22:22

基于微信小程序的景区实名核验与门票预约服务系统(程序+文档+讲解)

温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台…

作者头像 李华
网站建设 2026/9/1 1:21:11

长视频AI总结工具盘点:2026年6款产品功能与使用场景

两三个小时的课程、访谈或会议视频&#xff0c;可以先让AI生成摘要、章节和思维导图&#xff0c;再回到逐字稿或时间位置查看细节。 这篇盘点6款长视频总结工具&#xff0c;帮助你快速了解它们能处理哪些长内容。 先看这几款工具工具支持版本这篇里主要能做什么Ai好记网页端、A…

作者头像 李华
网站建设 2026/9/1 1:21:09

2026年6款AI视频学习工具:从视频总结、问答到复习笔记

用AI学习视频&#xff0c;可以先快速看重点&#xff0c;再通过逐字稿、导图、画面笔记和问答补充细节&#xff0c;最后整理成自己的复习资料。 这篇盘点6款视频学习工具&#xff0c;看看它们分别覆盖学习过程中的哪些环节。 先看这几款工具工具支持版本这篇里主要能做什么Noteb…

作者头像 李华
网站建设 2026/9/1 1:20:20

如何实现千牛订单批量处理自动化?单机管理200+店铺零关联的底层架构

如何实现千牛订单批量处理自动化&#xff1f;单机管理200店铺零关联的底层架构 店群运营的本质不是开多少店&#xff0c;而是单店运营成本能不能压到零。千牛的订单批量处理&#xff0c;是店群运营中最耗人力也最容易出错的环节。 店群日均订单量大&#xff0c;打单发货是纯重…

作者头像 李华
网站建设 2026/9/1 1:19:23

onnxruntime-win-x86-1.16.2.zip 部署指南:32位Windows下的模型推理实践

简介&#xff1a;本资源是专为Windows 32位平台定制的ONNX Runtime C推理引擎分发包&#xff08;v1.16.2&#xff09;&#xff0c;面向C开发者及嵌入式AI部署工程师&#xff0c;解决在x86环境下的轻量级模型推理集成难题&#xff0c;尤其适用于资源受限设备、工业控制终端或需兼…

作者头像 李华
网站建设 2026/9/1 1:18:27

HLW8112电能计量芯片开发:STM32通过SPI与UART读取数据全解析

简介&#xff1a;本资源是一套面向嵌入式开发工程师与STM32初学者的HLW8112电能计量芯片实战开发例程&#xff0c;聚焦SPI与UART双通信接口在STM32平台上的完整驱动实现&#xff0c;解决电能参数&#xff08;电压、电流、功率、电能&#xff09;采集与传输的核心问题。压缩包共…

作者头像 李华