三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

单例模式在C++中的使用:原子操作

单例模式在C++中的使用:原子操作

原子操作

在 C++11 中将原子操作纳入了标准,我们可以通过标准提供的原子操作来处理该问题。

通过给原子变量设置 std::std::memory_order_xxx 来防止 CPU 的指令重排操作。

#include <atomic> #include <mutex> class Singleton { private: static std::atomic<Singleton*> s_instancePtr; static std::mutex s_mutex; public: static Singleton* instance() { Singleton* sin = s_instancePtr.load(std::memory_order_acquire); if (nullptr == s_instancePtr) { std::lock_guard<std::mutex> lock(s_mutex); sin = s_instancePtr.load(std::memory_order_relaxed); if (nullptr == s_instancePtr) { sin = new Singleton(); s_instancePtr.store(sin, std::memory_order_release); } } return sin; } private: // 省略构造函数的处理 }; std::atomic<Singleton*> Singleton::s_instancePtr; std::mutex Singleton::s_mutex;

Meyers单例

其实还有一种简单的单例方式,那就是所谓的 Meyers 单例。

该方式在函数内部定义一个局部静态变量,并直接将该变量返回即可。

在 C++11 中保证了会以线程安全的方式初始化一个静态局部变量,因此可以放心使用。

static Singleton& instance() { static Singleton s_instance; return s_instance; }

在《Effective C++》一书中提到:任何一种 non-const static 对象,不论它是 local 还是 non-local,在多线程环境下“等待某事发生”都会有麻烦。

处理这个麻烦的一种做法是:在程序的单线程启动阶段,手工调用所有 reference-returning 函数,这可能消除与初始化有关的“竞速形式”。

← 返回列表