目录
可以回收的单例设计模式的类代码
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <list>
#include <thread>
#include <chrono>
#include <mutex>
using namespace std;
class MyCAS
{
private:
static MyCAS* m_instance;
MyCAS() {}
MyCAS(const MyCAS& obj) {}
MyCAS operator = (const MyCAS& obj) {}
public:
static MyCAS* GetInstance()
{
if (m_instance == NULL)
{
m_instance = new MyCAS();
static GC gc;
}
return m_instance;
}
class GC
{
public:
~GC()
{
if (MyCAS::m_instance != NULL)
{
delete MyCAS::m_instance;
MyCAS::m_instance = NULL;
}
}
};
};
MyCAS* MyCAS::m_instance = NULL;
int main()
{
MyCAS* p_a = MyCAS::GetInstance();
MyCAS* p_b = MyCAS::GetInstance();
printf("p_a=%p\n",p_a);
printf("p_b=%p\n",p_b);
return 0;
}
单例设计模式共享数据分析、解决
面临的问题:需要在我们自己创建的线程(而不是主线程)中来创建MyCAS这个单例类对象,这种线程可能不止一个(最少2个)。我们可能会面临GetInstance() 这种成员函数要互斥。
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <list>
#include <thread>
#include <chrono>
#include <mutex>
using namespace std;
std::mutex resource_mutex;
class MyCAS
{
private:
static MyCAS* m_instance;
MyCAS() {}
MyCAS(const MyCAS& obj) {}
MyCAS operator = (const MyCAS& obj) {}
public:
static MyCAS* GetInstance()
{
if (m_instance == NULL) //提高效率,避免多个线程,每次都要加锁
{
std::unique_lock<std::mutex> mymutex(resource_mutex);
if (m_instance == NULL)
{
m_instance = new MyCAS();
static GC gc;
}
}
return m_instance;
}
class GC
{
public:
~GC()
{
if (MyCAS::m_instance != NULL)
{
delete MyCAS::m_instance;
MyCAS::m_instance = NULL;
}
}
};
};
MyCAS* MyCAS::m_instance = NULL;
void mythread()
{
cout << "我的线程开始执行了...\n" << endl;
MyCAS* p_a = MyCAS::GetInstance();
cout << "我的线程执行完毕了...\n" << endl;
return;
}
int main()
{
//虽然这两个线程都是同一个入口函数,但毕竟是2个线程,所以同时有2条通路开始执行 同一块代码,由于线程切换,肯定会出问题的。
std::thread myobj1(mythread);
std::thread myobj2(mythread);
myobj1.join();
myobj2.join();
return 0;
}
std::call_once()
三、std::call_once() 是一个函数模板,C++11引入的函数,该函数的第二参数是一个函数名a()
功能:
1.能够保证函数a(),只被调用一次。它具备互斥量这种能力的,而且效率上,比互斥量消耗的资源更少;
2.call_once()需要和一个标记结合使用,这个标记std::once_flag;其实once_flag是一个结构;
3.call_once()就是通过这个标记来决定对应的函数a()是否执行,调用call_once()成功后,call_once()就把这个标记设置为一种已调用的状态,后续再次调用call_once的时候,只要once_flag为已调用转态,那么对应的函数a()就不会在被执行了。
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <list>
#include <thread>
#include <chrono>
#include <mutex>
using namespace std;
std::mutex resource_mutex;
std::once_flag g_flag; //这是个系统对应的标记
class MyCAS
{
static void CreateInstance() //只被调用一次
{
if (m_instance == NULL)
{
m_instance = new MyCAS();
cout << " CreateInstance() 被执行了" << endl;
static GC gc;
}
}
private:
static MyCAS* m_instance;
MyCAS() {}
MyCAS(const MyCAS& obj) {}
MyCAS operator = (const MyCAS& obj) {}
public:
static MyCAS* GetInstance()
{
//if (m_instance == NULL) //提高效率,避免多个线程,每次都要加锁
//{
// std::unique_lock<std::mutex> mymutex(resource_mutex);
// if (m_instance == NULL)
// {
// CreateInstance();
// }
//}
CreateInstance();
std::call_once(g_flag, CreateInstance); //call_once 保证CreateInstance只被调用一次
return m_instance;
}
class GC
{
public:
~GC()
{
if (MyCAS::m_instance != NULL)
{
delete MyCAS::m_instance;
MyCAS::m_instance = NULL;
}
}
};
};
MyCAS* MyCAS::m_instance = NULL;
void mythread()
{
cout << "我的线程开始执行了...\n" << endl;
MyCAS* p_a = MyCAS::GetInstance();
cout << "我的线程执行完毕了...\n" << endl;
return;
}
int main()
{
//虽然这两个线程都是同一个入口函数,但毕竟是2个线程,所以同时有2条通路开始执行 同一块代码,由于线程切换,肯定会出问题的。
std::thread myobj1(mythread);
std::thread myobj2(mythread);
myobj1.join();
myobj2.join();
return 0;
}