面向对象设计与分析40讲(17)双重检查锁定(double-checked locking)范式

双重检查锁定(也称为“双重检查锁定优化”)是一种用于减少获取锁的开销的软件设计模式。它通过在获取锁之前测试锁定条件(即“锁提示”)来实现。只有在锁定条件检查表明需要锁定时才会进行锁定操作。

#include <atomic>
#include <mutex>

class Singleton {
   
 public:
  static Singleton* GetInstance();

 private:
  Singleton() = default;

  static std::atomic<Singleton*> s_instance;
  static std::mutex s_mutex;
};

Singleton* Singleton::GetInstance() {
   
  Singleton* p = s_instance.load(std::memory_order_acquire); // A
  if (p == nullptr) {
    // 1st check
    std::lock_guard<std::mutex> lock(s_mutex);
    p = s_instance.load(std::memory_order_relaxed);
    if (p == nullptr) {
    // 2nd (double) check
      p = new Singleton();
      s_instance.store(p, std::memory_order_release); // B
    }
  }
  return p;
}

memory_order_acquire主要保证两个事情:

  • 相同原子变量的release操作此处可见
  • 创建一个同步(synchronization)边界,任何读写都不会被重排到该操作之前

memory_order_release主要保证两个事情:

  • 内存写操作对acquire相同原子变量的线程可见
  • 创建一个同步(synchronization)边界,任何读写都不会被重排到该操作之后

即假设A、B两个线程同时运行于A、B点,B的release操作对线程A可见。同时p = new Singleton()的读写操作不会被重排到B点之后。

C++ 11提供了基于该范式实现的基础设施std::once_flag和std::call_once:

#include <mutex>
#include <optional> // Since C++17

// Singleton.h
class Singleton {
   
 public:
  static Singleton* GetInstance();
 private:
  Singleton() = default;

  static std::optional<Singleton> s_instance;
  static std::once_flag s_flag;
};

// Singleton.cpp
std::optional<Singleton> Singleton::s_instance;
std::once_flag Singleton::s_flag{
   };

Singleton* Singleton::GetInstance() {
   
  std::call_once(Singleton::s_flag,
                 []() {
    s_instance.emplace(Singleton{
   }); });
  return &*s_instance;
}

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-25 11:16:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-25 11:16:01       101 阅读
  3. 在Django里面运行非项目文件

    2023-12-25 11:16:01       82 阅读
  4. Python语言-面向对象

    2023-12-25 11:16:01       91 阅读

热门阅读

  1. ubuntu常用指令

    2023-12-25 11:16:01       61 阅读
  2. C语言例题6

    2023-12-25 11:16:01       53 阅读
  3. Android 10 实现随机分配 MAC 地址

    2023-12-25 11:16:01       58 阅读
  4. 150. 逆波兰表达式求值

    2023-12-25 11:16:01       56 阅读
  5. SQL语句分类

    2023-12-25 11:16:01       62 阅读
  6. AWS认证SAA-C03每日一题

    2023-12-25 11:16:01       46 阅读