Emai : hahayacoder@gmail.com
背景
最近在公司的项目中,经常会用到单例模式,由于之前没有想过怎么正确使用单例模式,导致写成的程序中有BUG。在学习Cocos2d-x时,导演类CCDirector等都是单例类。所以从头开始学习单例模式。
介绍
单例模式也称为单件模式,单子模式.使用单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有模块共享.有很多地方需要这样的功能模块,如系统的日志输出、人物管理器等。单例模式一般实现方式为:将类的构造函数定义成私有,定义一个私有的静态变量指针指向类得唯一实例,并提供一个公有静态方法获取该实例
简单实现
//Singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
class Singleton
{
public:
static Singleton* getInstance();
private:
Singleton();
static Singleton* m_singleton;
};
#endif // SINGLETON_H
//Singleton.cpp
#include "singleton.h"
#include <iostream>
using namespace std;
//static变量的定义
Singleton* Singleton::m_singleton = NULL;
Singleton* Singleton::getInstance()
{
if(NULL == m_singleton)
{
m_singleton = new Singleton();
cout << "Singleton Create..." << endl;
}
return m_singleton;
}
Singleton::Singleton()
{
}
//main.cpp
#include "singleton.h"
#include <QtCore/QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Singleton *A = Singleton::getInstance();
Singleton *B = Singleton::getInstance();
return a.exec();
}
运行结果:
从运行结果可以知道Singleton对象只创建了一次,即创建两个Singleton对象发现只打印出一次Create... 即只调用了一次构造函数只生成了一个实例
深入思考
当在多线程中使用单例模式时(假设有A、B两个线程),同时调用getInstance函数,初始时m_singleton为NULL,当A线程调用getInstance时,执行到if(NULL==m_singleton)时,由于此时m_singleton为NULL,默认情况下是要执行if里面的语句,但是由于CPU时间片到了等原因,先要去执行B线程,B线程执行到if(NULL==m_singleton)时,此时m_singleton同样为NULL。这种情况下就会出现问题,下面使用Qt中的互斥锁重写代码
//Singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
#include <QMutex>
#include <QMutexLocker>
class Singleton
{
public:
static Singleton* getInstance();
private:
Singleton();
//定义静态成员 静态成员不属于某个对象 是属于整个类
static Singleton* m_singleton;
static QMutex mutex;
};
#endif // SINGLETON_H
//Singleton.cpp
#include "singleton.h"
#include <iostream>
using namespace std;
//static变量的定义
QMutex Singleton::mutex;
Singleton* Singleton::m_singleton = NULL;
Singleton* Singleton::getInstance()
{
//加锁
mutex.lock();
if(NULL == m_singleton)
{
m_singleton = new Singleton();
cout << "Singleton Create..." << endl;
}
//解锁
mutex.unlock();
return m_singleton;
}
Singleton::Singleton()
{
}