You need to enable JavaScript to run this app. C++类构造函数中如何为已声明的unique_lock关联对应mutex
优惠活动
大模型
产品
解决方案
定价
更多

C++类构造函数中如何为已声明的unique_lock关联对应mutex

类内互斥量与对应unique_lock的关联实现

std::unique_lock默认构造出来是空锁状态,不会自动和任何互斥量建立关联,内部仅保存一个空的mutex指针,必须手动传入目标互斥量的地址才能完成绑定。

实现过程中需要重点规避两个问题:

  • 绑定锁时不能直接触发加锁,不然构造类对象时就会把所有互斥量独占,直接造成死锁,需要用std::defer_lock标记,仅建立关联、不主动获取锁的所有权
  • 类成员的析构顺序和声明顺序完全相反,必须保证绑定了mutex的unique_lock,比被绑定的mutex更早析构,不然程序退出时unique_lock会访问已经销毁的mutex,触发未定义行为

调整类成员声明顺序

原类的成员声明顺序会导致析构时先销毁被unique_lock关联的mutex,必须调整为如下顺序:

#include <iostream>
#include <mutex>
#include <string>

#define PHILO_NUM 5
class philosophers
{
private:
    // 先声明所有被关联的互斥量,保证它们的析构时机晚于对应的unique_lock
    std::mutex _mu[PHILO_NUM];
    std::mutex _screenMutex;
    // 再声明对应的unique_lock对象,析构时会先销毁这部分unique_lock,再销毁前面的互斥量
    std::unique_lock<std::mutex> _fork[PHILO_NUM];
    std::unique_lock<std::mutex> _screen;
public:
    philosophers();
};

构造函数内完成绑定

利用unique_lock的移动赋值特性,在循环和函数末尾完成对应关系绑定:

#include "philosophers.h"

philosophers::philosophers()
{
    for (int i = 0; i < PHILO_NUM; i++)
    {
        // 将_fork[i]绑定到对应的_mu[i],defer_lock表示仅关联、不主动加锁
        _fork[i] = std::unique_lock<std::mutex>(&_mu[i], std::defer_lock);
    }
    // 将_screen绑定到屏幕互斥量,同样仅关联不主动加锁
    _screen = std::unique_lock<std::mutex>(&_screenMutex, std::defer_lock);
}

实现细节说明

  • 绑定的时候必须传入互斥量的地址,unique_lock内部存储的是对应mutex的指针,无法直接绑定mutex的副本
  • std::defer_lock是必填参数,省略的话构造临时unique_lock时会立刻阻塞给对应mutex加锁,类构造完成时所有叉子、屏幕锁都会被独占,后续业务无法正常运行
  • 这种赋值方式完全合法:unique_lock是仅支持移动语义的类型,右侧构造的临时对象是右值,赋值时会直接把内部持有的mutex指针转移给左侧成员,没有额外拷贝开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.07 19:36:03