版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
#include <iostream>
#include <mutex>
#include <thread>
std::mutex myMutex;
//call_once的标记
std::once_flag myFlag;
class MyClassA
{
private:
static MyClassA* classAInstance;
//禁止在外部通过此方法创建该类
MyClassA() {};
public:
static MyClassA* getInstance()
{
//双重判断,只会在第一次的时候进行执行,然后多个线程进去创建instance,
//但是只能有一个抢到锁,创建完毕之后释放,其他的进来,instance已经不是NULL了
//虽然初始化的时候会有可能很多线程进来创建instance,但是最终只能有一个instance完成实例化
//并且之后使用的时候,第一个if就不为NULL了,也就不用进行锁的互斥了
//然后getInstance()方法就是多线程安全且高效的了
if (classAInstance == NULL)
{
std::unique_lock<std::mutex> myUniqueLock(myMutex);
if (classAInstance == NULL)
{
classAInstance = new MyClassA();
static finalReleaseReourcesClass releaseClass;
}
}
return classAInstance;
}
//最终代码的方式释放资源,这是一个内部类
//虽然说线程执行结束之后会自己释放内存,
//使用内部类的目的就是在代码上就直接给他释放掉内存
class finalReleaseReourcesClass
{
public:
~finalReleaseReourcesClass()
{
if (MyClassA::classAInstance)
{
delete MyClassA::classAInstance;
MyClassA::classAInstance = NULL;
}
}
};
//下面的private是创建单例的方法,可以看到,这里没有双重保护,这也是把它设为
//private的原因之一,因为我们要在下面的public方法里面进行call_once的使用,
//效果上和双重判断是一样的
private:
static void createInstance()
{
classAInstance = new MyClassA();
std::cout << "thread "<<std::this_thread::get_id()<<"执行了createInstance" << std::endl;
static finalReleaseReourcesClass releaseClass;
}
public:
static MyClassA* getInstance2()
{
//这里call_once的作用跟双重判断的作用一样,但是占用的资源更小,效率更高
std::call_once(myFlag, createInstance);
return classAInstance;
}
};
//初始化实例为空
MyClassA* MyClassA::classAInstance = NULL;
//之所以写这个方法,就是为了让多个线程进行同时获取单例,这是线程的入口函数
void beginMyThread()
{
std::cout << "thread " << std::this_thread::get_id() << " begin " << std::endl;
MyClassA* ptr = MyClassA::getInstance2();
std::cout << "thread " << std::this_thread::get_id() << " end " << std::endl;
}
int main()
{
//MyClassA* myPtr1 = MyClassA::getInstance();
//MyClassA* myPtr2 = MyClassA::getInstance();
//MyClassA* myPtr3 = MyClassA::getInstance();
//MyClassA* myPtr4 = MyClassA::getInstance();
//单例设计模式数据共享问题
//call_once():具备互斥量的能力,且比互斥量更加高效,需要用一个标记once_flag
//第二个参数是一个函数名
std::thread myThreadOne(beginMyThread);
std::thread myThreadTwo(beginMyThread);
myThreadOne.join();
myThreadTwo.join();
}