第一种写法:
这种方法又叫做 Meyers' SingletonMeyer's的单例, 是著名的写出《Effective C++》系列书籍的作者 Meyers 提出的。所用到的特性是在C++11标准中的Magic Static特性:
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束。
这样保证了并发线程在获取静态局部变量的时候一定是初始化过的,所以具有线程安全性。
第二种写法
智能指针和双检锁
shared_ptr和mutex都是C++11的标准,以上这种方法的优点是
- 基于 shared_ptr, 用了C++比较倡导的 RAII思想,用对象管理资源,当 shared_ptr 析构的时候,new 出来的对象也会被 delete掉。以此避免内存泄漏。
- 加了锁,使用互斥量来达到线程安全。这里使用了两个 if判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁,避免每次调用 get_instance的方法都加锁,锁的开销毕竟还是有点大的。
- 不足之处在于: 使用智能指针会要求用户也得使用智能指针,非必要不应该提出这种约束; 使用锁也有开销; 同时代码量也增多了,实现上我们希望越简单越好。
第三种写法
智能指针和call_once
同上
#include <iostream>
#include <thread>
#include <memory>
#include <mutex>
using namespace std;
//------------------------------------局部静态成员变量---------------------------------//
//如果当静态局部变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束。
//这样保证了并发线程在获取静态局部变量的时候一定是初始化过的,所以具有线程安全性。
/*
class Singleton{
private:
Singleton() {
cout << "constructor" << endl;
}
public:
~Singleton() {
cout << "deconstructor" << endl;
}
static Singleton & getInstance() {
static Singleton instance;
return instance;
}
};
*/
//---------------------------------局部静态成员变量 end-------------------------------------------//
//------------------------------------双检锁---------------------------------//
/*
class Singleton { //双检锁
private:
Singleton() {
cout << "constructor" << endl;
}
public:
typedef std::shared_ptr<Singleton> Ptr;
~Singleton() {
cout << "deconstructor" << endl;
}
static std::shared_ptr<Singleton> getInstance() {
if (m_instance_ptr == nullptr) { //只有判断指针为空的时候才加锁,避免每次调用 getInstance的方法都加锁
std::lock_guard<std::mutex> lg(m_mutex);
if (m_instance_ptr == nullptr) {
m_instance_ptr = std::shared_ptr<Singleton>(new Singleton);
}
return m_instance_ptr;
}
}
private:
static std::shared_ptr<Singleton> m_instance_ptr;
static std::mutex m_mutex;
};
//静态成员变量的初始化
Singleton::Ptr Singleton::m_instance_ptr = nullptr;
std::mutex Singleton::m_mutex;
*/
//--------------------------------------双检锁 end---------------------------------------------//
//------------------------------------call_once start-------------------------------------//
std::once_flag s_flag;
class Singleton {
private:
Singleton() {
cout << "constructor" << endl;
}
static void createInstance() {
m_instance_ptr = std::shared_ptr<Singleton>(new Singleton);
}
public:
typedef std::shared_ptr<Singleton> Ptr;
~Singleton() {
cout << "deconstructor" << endl;
}
static std::shared_ptr<Singleton> getInstance() {
std::call_once(s_flag, createInstance);
return m_instance_ptr;
}
private:
static std::shared_ptr<Singleton> m_instance_ptr;
};
//静态成员变量的初始化
Singleton::Ptr Singleton::m_instance_ptr = nullptr;
//------------------------------------call_once end--------------------------------------//
void mythread() {
cout << "child thread start" << endl;
//Singleton& instance = Singleton::getInstance(); //类内静态成员变量
//Singleton::Ptr instance = Singleton::getInstance(); //双检锁
Singleton::Ptr instance = Singleton::getInstance(); //call_once
cout << "child thread end" << endl;
}
int main() {
std::thread my_thread_1(mythread);
std::thread my_thread_2(mythread);
my_thread_1.join();
my_thread_2.join();
return 0;
}