C++ 超时互斥锁(Timed Mutex):std::timed_mutex 与 std::unique_lock

C++ 超时互斥锁(Timed Mutex):std::timed_mutex 与 std::unique_lock

flyfish

术语对照表

中文术语 英文术语 定义
超时互斥锁 Timed Mutex 支持限时获取锁的互斥锁,超时后返回失败而非无限阻塞
限时等待 Timed Wait 在指定时长或时间点内反复尝试获取资源
非阻塞放弃 Timeout Fallback 获取失败后执行替代路径的行为
延迟加锁 Deferred Locking 先持有锁管理对象、后手动触发加锁的策略
锁所有权 Lock Ownership 锁当前归哪个线程持有,由该线程负责解锁

一、概述

超时互斥锁(Timed Mutex)在互斥锁的基础上扩展了获取策略:除无限等待的 lock() 外,提供限时等待接口。当等待超时仍未获得锁时,接口返回失败,调用方可以执行替代路径,从而避免线程被永久阻塞。

std::timed_mutex 是 C++ 标准库对超时互斥锁的实现。其限时能力必须由 std::unique_lock 配合 std::defer_lock 与 try_lock_for 才能完整使用。

二、原理

2.1 等待策略的三种形态

接口 等待上限 语义
lock() 无上限 无限阻塞,直至获得锁
try_lock() 零 单次尝试,未获得立即返回 false
try_lock_for(时长) / try_lock_until(时间点) 指定时长或时间点 限时反复尝试,超时返回 false

三种形态分别对应无限等待、无等待、限时等待三类需求。

2.2 限时等待的工程价值

无限阻塞的锁存在系统性风险:持锁线程若因异常或逻辑错误长期不释放,所有等待线程将被连带阻塞,程序表现为不可恢复的停滞。限时等待将等待行为置于调用方控制之下:超时后放弃,转而执行替代逻辑或记录错误,阻断故障扩散。

三、接口规范

std::timed_mutex 除继承互斥锁全部接口外,新增:

接口 参数 行为
try_lock_for 时长(std::chrono::duration) 在指定时长内反复尝试,超时返回 false
try_lock_until 时间点(std::chrono::time_point) 等待至指定时刻,超时返回 false

四、使用方式

4.1 不推荐:std::lock_guard 包装超时互斥锁

cpp 复制代码
std::timed_mutex tmtx;

void worker() {
    std::lock_guard<std::timed_mutex> lock(tmtx);   // 合法,但限时能力未启用
}

std::lock_guard 构造时调用的是 lock(),即无限等待语义。该写法虽可编译,但超时互斥锁的限时能力完全闲置,等价于普通互斥锁。

4.2 正确:std::unique_lock 配合 std::defer_lock

cpp 复制代码
#include <chrono>
#include <mutex>

std::timed_mutex tmtx;
int shared_state = 0;

bool try_update() {
    // 阶段一:构造锁管理对象,指定延迟加锁策略,此时未持有锁
    std::unique_lock<std::timed_mutex> lock(tmtx, std::defer_lock);

    // 阶段二:限时获取锁
    if (lock.try_lock_for(std::chrono::seconds(2))) {
        ++shared_state;                 // 已获得锁,临界区
        return true;                    // 析构时自动解锁
    }

    // 阶段三:超时分支,锁管理对象析构时不做任何操作
    return false;
}

执行阶段说明:

  1. 延迟加锁:defer_lock 使 unique_lock 持有锁的管理权但不加锁,为后续选择加锁方式保留余地。
  2. 限时获取:try_lock_for 在指定时长内反复尝试,获得锁返回 true 并进入临界区,超时返回 false。
  3. 确定性释放:获得锁时析构自动解锁;未获得锁时析构为空操作。两种终态均无需手动干预。

4.3 多线程竞争示例

cpp 复制代码
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>

std::timed_mutex tmtx;

void worker(int id) {
    std::unique_lock<std::timed_mutex> lock(tmtx, std::defer_lock);
    if (lock.try_lock_for(std::chrono::milliseconds(300))) {
        std::cout << "thread " << id << " acquired lock\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    } else {
        std::cout << "thread " << id << " timed out\n";
    }
}

int main() {
    std::thread t1(worker, 1);
    std::thread t2(worker, 2);
    std::thread t3(worker, 3);
    t1.join();
    t2.join();
    t3.join();
    return 0;
}

输出

bash 复制代码
thread 1 acquired lock
thread 3 acquired lock
thread 2 timed out

三个线程竞争同一把超时互斥锁,仅首个获得锁;其余线程在限时内未获得锁,转入超时分支执行替代逻辑,全程无线程无限阻塞。

相关推荐
今天要早睡_2 小时前
C++01_入门基础复习
开发语言·c++
Fuyo_11195 小时前
C++ 运行时多态与虚函数机制全面剖析【面试重点】
开发语言·c++·面试
Chen_harmony7 小时前
七、STL与string类
开发语言·c++
xxxiugou1237 小时前
C++命名空间与引用全解析
开发语言·c++
用户7624117567058 小时前
第十五章 人工智能基础
c++
爱写Bug的浮游11 小时前
unique_ptr 零开销的真相与边界
c++·facebook
xiaoye-duck11 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(下):流式响应实现和测试
网络·c++·语言模型·chatgpt
落樱弥城13 小时前
Perf 逐步探查性能缺口并优化
c++·性能优化
坤坤子吖13 小时前
Linux网络编程:UDP进阶,从字典服务器到简单聊天室
linux·服务器·网络·c++·笔记·学习