单例模式:确保一个类只有一个实例,并提供一个全局访问点。
在实际工作中,写控制软件时候,我都会写一个控制中心类,所有的控制都通过这个控制中心类来操作,所以这个控制类只允许实例一个对象。
实现单例模式有两种:一种是懒汉式,一种是饿汉式。
懒汉式 实例如下:
class Single
{
private:
Single()
{
cout<<"begin create"<<endl;
Sleep(1000);
cout <<"end create"<<endl;
}
public:
static Single* getInstance()
{
//懒汉式
if (m_pSing == NULL)
{
m_pSing = new Single;
}
return m_pSing;
}
void FreeSingle()
{
if (m_pSing != nullptr)
{
delete m_pSing;
m_pSing = nullptr;
}
}
private:
static Single* m_pSing;
};
//懒汉式
Single* Single::m_pSing = nullptr;
int main()
{
Single* pS1 = getInstance();
Single* pS2 = getInstance();
if (pS1 == pS2)
{
cout << "两个对象相同"<<endl;
}
else
{
cout << "两个对象不相同" <<endl;
}
return 0;
}
饿汉式示例:
static Single* getInstance()
{
return m_pSing;
}
//饿汉式
Single* Single::m_pSing = new Single;
饿汉式变化的地方就是在初始化时,就把对象构造出来。这样也就只有一个构造对象了。这种模式的对象实际上在运行Single* pS1 = getInstance(),这个之前就已经构造完毕。
在多线程中,如果都运行getInstance的话,饿汉式由于初始化就已经构造完毕,不会出现问题。但是懒汉式会由于线程同步问题,会多次进出getInstance,导致构造了多个对象。要避免这个问题,只需要在getInstance里加入互斥即可。
示例:
std::mutex m_Mutex;
class Single
{
private:
Single()
{
cout<<"begin create"<<endl;
Sleep(1000);
cout <<"end create"<<endl;
}
public:
static Single* getInstance()
{
//懒汉式
if (m_pSing == NULL) //第一次检查
{
m_Mutex.lock();
if (m_pSing == NULL) //等待上个线程执行完毕,需要再次检查
{
m_pSing = new Single;
}
m_Mutex.unlock();
}
return m_pSing;
}
void FreeSingle()
{
if (m_pSing != nullptr)
{
delete m_pSing;
m_pSing = nullptr;
}
}
private:
static Single* m_pSing;
};
//懒汉式
Single* Single::m_pSing = nullptr;
void CreateSingleFunc(Single* &pS)
{
pS = Single::getInstance();
}
int main()
{
Single* pS1 = nullptr;
Single* pS2 = nullptr;
std::thread pThread1(&CreateSingleFunc,ref(pS1));
std::thread pThread2(&CreateSingleFunc,ref(pS2));
pThread1.join();
pThread2.join();
if (pS1 == pS2)
{
cout << "两个对象相同"<<endl;
}
else
{
cout << "两个对象不相同" <<endl;
}
return 0;
}
需要注意的是在getInstance里,必须做二次检查是否为NULL。