You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译期未知vector大小时,如何安全锁定所有mutex并生成lock guard?

解决方案:运行时批量锁定动态数量的互斥量

当互斥量的数量只能在运行时确定时,std::scoped_lock的编译期固定参数版本不再适用,我们可以通过以下两种安全方式实现批量锁定:

方法1:std::lock + std::unique_lock 组合

std::lock支持接收一组延迟锁定的unique_lock,并通过防死锁算法一次性锁定所有互斥量,之后由unique_lock自动管理锁的生命周期:

#include <vector>
#include <mutex>

// 建议直接用成员对象替代裸指针,避免手动内存管理风险
struct Element {
    std::mutex mut;
    // 保留原指针版本兼容(不推荐):
    // std::mutex* mut = new std::mutex();
    // Element(Element&& other) : mut(other.mut) { other.mut = nullptr; }
    // ~Element() { delete mut; }
};

int main() {
    std::vector<Element> v;
    v.emplace_back();
    v.emplace_back();
    v.emplace_back();

    // 创建延迟锁定的unique_lock集合
    std::vector<std::unique_lock<std::mutex>> defer_locks;
    defer_locks.reserve(v.size());
    for (auto& elem : v) {
        defer_locks.emplace_back(elem.mut, std::defer_lock);
    }

    // 一次性锁定所有互斥量,避免死锁
    std::lock(std::begin(defer_locks), std::end(defer_locks));

    // 临界区代码:此时所有互斥量已被安全锁定
    // ...

    // 作用域结束时,defer_locks会自动解锁所有互斥量
}

方法2:C++20及以上版本使用std::scoped_lock初始化列表构造

C++20扩展了std::scoped_lock,支持直接接收延迟锁定的unique_lock列表,写法更简洁:

#include <vector>
#include <mutex>

struct Element {
    std::mutex mut;
};

int main() {
    std::vector<Element> v;
    v.emplace_back();
    v.emplace_back();
    v.emplace_back();

    std::vector<std::unique_lock<std::mutex>> defer_locks;
    defer_locks.reserve(v.size());
    for (auto& elem : v) {
        defer_locks.emplace_back(elem.mut, std::defer_lock);
    }

    // 直接用延迟锁定列表构造scoped_lock,自动完成批量锁定
    std::scoped_lock lock(std::move(defer_locks));

    // 临界区代码
    // ...
}

关键注意点

  • 优先使用std::mutex作为Element的成员对象,避免裸指针带来的内存泄漏、空指针等风险。
  • std::lock和std::scoped_lock都会采用防死锁的顺序锁定互斥量,比手动逐个锁定更安全。
  • 如果需要临时解锁部分互斥量,std::unique_lock提供了unlock()方法,灵活性优于std::lock_guard。

内容的提问来源于stack exchange,提问作者calvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 00:32:39