多线程安全的单例模式

目标: 写一个分配内存的类,并用单利模式来进行管理

方案一双重检查锁定

class CPUDeviceAllocatorFactory {
 public:
  static std::shared_ptr<CPUDeviceAllocator> get_instance() {
    if (instance == nullptr) { // First check (no locking)
      std::lock_guard<std::mutex> lock(mutex_);
      if (instance == nullptr) { // Second check (with locking)
        instance = std::make_shared<CPUDeviceAllocator>();
      }
    }
    return instance;
  }

 private:
  static std::shared_ptr<CPUDeviceAllocator> instance;
  static std::mutex mutex_;
};

std::shared_ptr<CPUDeviceAllocator> CPUDeviceAllocatorFactory::instance = nullptr;
std::mutex CPUDeviceAllocatorFactory::mutex_;

方案二使用std::call_once

std::call_once 保证某个操作只会执行一次,并且是线程安全的。可以用于初始化单例实例。

#include <mutex>

class CPUDeviceAllocatorFactory {
 public:
  static std::shared_ptr<CPUDeviceAllocator> get_instance() {
    std::call_once(flag, []() {
      instance = std::make_shared<CPUDeviceAllocator>();
    });
    return instance;
  }

 private:
  static std::shared_ptr<CPUDeviceAllocator> instance;
  static std::once_flag flag;
};

std::shared_ptr<CPUDeviceAllocator> CPUDeviceAllocatorFactory::instance = nullptr;
std::once_flag CPUDeviceAllocatorFactory::flag;

方案三静态函数变量

class CPUDeviceAllocatorFactory {
 public:
  static std::shared_ptr<CPUDeviceAllocator> get_instance() {
    static std::shared_ptr<CPUDeviceAllocator> instance = std::make_shared<CPUDeviceAllocator>();
    return instance;
  }
};

代码分析

  • 静态局部变量instanceget_instance 函数的一个静态局部变量,这意味着它只会在第一次调用 get_instance 时被初始化,而后续对 get_instance 的调用都将返回这个已经初始化的对象。

  • 线程安全:在 C++11 标准中,静态局部变量的初始化是线程安全的。这意味着多个线程同时访问 get_instance 时,静态局部变量 instance 只会被正确地初始化一次,其他线程会等待初始化完成后再获取该实例。

  • 简洁性:使用静态局部变量的方式相较于双重检查锁定或 std::call_once 的方式更为简洁,不需要额外的锁或标记位。

总结

使用静态函数变量是实现线程安全单例模式的简洁且有效的方式,特别是在 C++11 及更高版本中,它避免了使用锁定机制的复杂性,同时确保了初始化的线程安全性。因此,这种方法是一种推荐的实现方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值