news 2026/1/11 1:15:13

unique_lock<mutex> uLock 的用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
unique_lock<mutex> uLock 的用法

std::unique_lock<std::mutex>是 C++11 提供的一种更灵活的互斥锁管理器,常用于多线程同步场景。

std::unique_lock<std::mutex> uLock;
本质上是一个可控制加锁/解锁时机、可转移所有权的锁对象。

一、unique_lock是干什么的?

一句话总结:

unique_lock是 RAII 风格的互斥锁管理器,比lock_guard更灵活

特性lock_guardunique_lock
构造时自动加锁✅(可选)
析构时自动解锁
手动 lock / unlock
延迟加锁
可转移所有权
配合 condition_variable✅(必须)

二、最常见的用法(自动加锁)

std::mutex mtx;

void func()
{
std::unique_lock<std::mutex> uLock(mtx);
// 🔒 此处已加锁

// 临界区
do_something();

// 函数结束自动解锁
}
等价于:

mtx.lock();
do_something();
mtx.unlock();
异常安全(中途 return / throw 都会自动 unlock)。

三、延迟加锁(嵌入式常用)

1️⃣std::defer_lock

std::unique_lock<std::mutex> uLock(mtx, std::defer_lock);

// 此时还没加锁
do_prepare();

// 手动加锁
uLock.lock();

// 临界区
do_critical();

// 可手动提前解锁
uLock.unlock();

👉非常适合那种:

  • 先判断条件

  • 再决定是否进入临界区的逻辑

四、手动 unlock / 再 lock(lock_guard做不到)

std::unique_lock<std::mutex> uLock(mtx); do_part1(); // 暂时释放锁 uLock.unlock(); // 执行耗时操作 sleep(1); // 再次加锁 uLock.lock(); do_part2();

五、和condition_variable搭配(必须用unique_lock

标准生产者 / 消费者模型

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void consumer()
{
std::unique_lock<std::mutex> uLock(mtx);

cv.wait(uLock, [] { return ready; });
// wait 内部会:
// 1. unlock(mtx)
// 2. 阻塞等待
// 3. 被唤醒后 lock(mtx)

use_data();
}

void producer()
{
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
}

⚠️重点:

  • cv.wait()只能接受unique_lock

  • 因为它需要在内部反复 unlock / lock

六、尝试加锁(try_lock)

std::unique_lock<std::mutex> uLock(mtx, std::try_to_lock);

if (uLock.owns_lock())
{
// 成功拿到锁
}
else
{
// 没拿到锁,直接返回
}
👉适合避免线程阻塞的场景(例如:状态上报、非关键日志)。

七、转移锁的所有权(高级用法)

std::unique_lock<std::mutex> lock1(mtx);

// 转移所有权
std::unique_lock<std::mutex> lock2 = std::move(lock1);

if (!lock1.owns_lock())
{
// lock1 已失效
}

📌 这个在:

  • 线程池

  • 任务队列

  • 跨函数返回锁
    场景中很有用。

八、与lock_guard的选择建议(记住这张表)

场景用哪个
简单临界区lock_guard
需要 wait / notifyunique_lock
需要手动 unlockunique_lock
延迟加锁unique_lock
try_lockunique_lock

👉经验法则

能用lock_guard就别用unique_lock,但一旦复杂,就直接unique_lock

九、典型用法(示例)

线程 + sleep / yield / 任务队列,典型写法应该是:

std::mutex mtx;

void worker()
{
while (running)
{
std::unique_lock<std::mutex> uLock(mtx);

if (task_queue.empty())
{
uLock.unlock();
std::this_thread::yield();
continue;
}

auto task = task_queue.front();
task_queue.pop();

uLock.unlock(); // 🔥 关键:避免锁内执行耗时任务

process(task);
}
}

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

探索金属凝固的奥秘:三维枝晶相场模拟的奇妙旅程

三维凝固金属枝晶生长相场模拟&#xff01; 首次实现三维凝固枝晶相场模拟&#xff5e; 根据经典三维模型 实现枝晶的各项异性凝固生长 完成相场和温度场变化情况&#xff01; 源代码实现&#xff0c;且可修改相关参数对应实际实验情况&#xff01; 增加维度 增加可能性&#x…

作者头像 李华
网站建设 2026/1/6 11:31:19

成本核算模型:每千次调用消耗多少电费

成本核算模型&#xff1a;每千次调用消耗多少电费 在AI推理成本高企的今天&#xff0c;一个现实问题摆在开发者面前&#xff1a;我能不能负担得起每天成千上万次的模型调用&#xff1f;尤其是当任务只是解一道算法题或写一段函数时&#xff0c;是否真的需要动用GPT-4级别的“重…

作者头像 李华
网站建设 2026/1/6 11:30:20

8 款 AI 开题报告工具测评:让论文开篇快人 N 步

论文开题到底能多轻松&#xff1f;现在的 AI 工具已经把 “烧脑写框架” 变成了 “填空式出稿”。今天就盘点 8 款实用的 AI 开题报告工具&#xff0c;PaperXie直接拿下 “性价比王者”&#xff0c;剩下 7 款各有特色 —— 看完这篇&#xff0c;你选工具再也不用踩坑&#xff0…

作者头像 李华
网站建设 2026/1/6 11:29:58

基于springboot + vue二手电子产品系统(源码+数据库+文档)

二手电子产品 目录 基于springboot vue二手电子产品系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue二手电子产品系统 一、前言 博主介绍&…

作者头像 李华
网站建设 2026/1/6 11:29:55

基于springboot + vue嗨玩旅游网站系统(源码+数据库+文档)

健身房管理系统 目录 基于springboot vue嗨玩旅游网站系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue嗨玩旅游网站系统 一、前言 博主介绍&am…

作者头像 李华
网站建设 2026/1/7 22:08:45

BeyondCompare4对比代码太麻烦?让VibeThinker先做逻辑预处理

BeyondCompare4对比代码太麻烦&#xff1f;让VibeThinker先做逻辑预处理 在日常开发中&#xff0c;你是否曾为两段“功能相同但写法迥异”的代码而头疼&#xff1f;明明知道它们都在实现快速排序&#xff0c;可BeyondCompare4却标出几十处红色差异——变量名不同、循环结构不一…

作者头像 李华