如何对std::vector<std::mutex>使用std::scoped_lock?
问题原因
std::scoped_lock是基于编译期变长模板参数实现的,要求入参的互斥量数量必须在编译阶段就确定,而std::vector是动态长度容器,内部存储的互斥量数量只有运行时才能获取,所以你的两种写法都无法通过编译:
std::scoped_lock lock{ mutexes }:std::scoped_lock没有接收单种std::vector<std::mutex>类型参数的构造函数,直接触发编译错误。std::scoped_lock lock{ ...mutexes }:参数包展开语法仅支持编译期确定长度的参数包,std::vector的动态长度无法在编译阶段展开,同样会报错。
解决方案
场景1:编译期可确定互斥量数量
如果你的互斥量个数是固定的,直接把std::vector替换为编译期固定长度的std::array,再通过辅助函数+索引序列展开参数即可使用std::scoped_lock:
#include <mutex> #include <array> #include <utility> // 辅助函数:展开std::array的元素作为scoped_lock的入参 template <size_t... I> std::scoped_lock<std::mutex...> make_array_scoped_lock(std::array<std::mutex, sizeof...(I)>& arr, std::index_sequence<I...>) { return std::scoped_lock(arr[I]...); } // 使用示例 constexpr size_t FIXED_MUTEX_NUM = 5; std::array<std::mutex, FIXED_MUTEX_NUM> mutexes; // 生成scoped_lock,自动持有所有互斥量直到出作用域 auto lock = make_array_scoped_lock(mutexes, std::make_index_sequence<FIXED_MUTEX_NUM>{});
场景2:运行时才能确定互斥量数量
如果确实需要动态调整互斥量的个数,就不能用std::scoped_lock,改用std::unique_lock配合std::lock实现同样的批量加锁、自动释放、避免死锁的效果:
#include <mutex> #include <vector> std::vector<std::mutex> mutexes; // 第一步:构造所有unique_lock,先不执行加锁 std::vector<std::unique_lock<std::mutex>> locks; locks.reserve(mutexes.size()); for (auto& m : mutexes) { locks.emplace_back(m, std::defer_lock); } // 第二步:批量加锁,std::lock内部会处理死锁规避逻辑 std::lock(locks.begin(), locks.end()); // locks出作用域时会自动逐个释放所有互斥量,无需手动处理
内容的提问来源于stack exchange,提问作者user16850544
相关产品推荐
相关产品推荐

