对于java而言,可以通过内部类实现单例的延迟加载:
public class Singleton {
private Singleton() {};
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
由于Java内部类只有在调用到的时候才会加载,并且JVM保证了加载的线程安全,因此这种单例模式是线程安全的。
对于C++而言,没有像JVM这样的类加载机制保证线程安全,因此单例情况比Java要复杂。
如果采用懒汉模式,主要有以下几种方式:
方式1:双重检测及加锁:
class Singleton
{
private:
static Singleton* m_instance;
Singleton(){}
public:
static Singleton* getInstance();
};
in Singleton.cpp:
Singleton* Singleton::getInstance()
{
if(NULL == m_instance)
{
Lock();//借用其它类来实现,如boost
if(NULL == m_instance)
{
m_instance = new Singleton;
}
UnLock();
}
return m_instance;
}
双重检测也有潜在问题,详情参考文末链接。
方式2:静态内部变量(C++11之前需加锁)
需要注意的是,C++11以后,要求编译器保证内部静态变量的线程安全性,可以不加锁。但C++ 11以前,仍需要加锁。
class Singleton
{
private:
Singleton(){}
public:
static Singleton* getInstance();
};
in Singleton.cpp:
Singleton* Singleton::getInstance()
{
Lock(); // not needed after C++0x
static Singleton instance;
UnLock(); // not needed after C++0x
return &instance;
}
方式3: 无锁设计:
如果既要懒汉模式,又要无锁设计,针对linux/unix平台, 可以采用pthread_once,例如:
class Singleton {
public:
static Singleton* instance();
static void init() { pIntance = new Singleton; }
...
private:
static Singleton* pInstance;
static pthread_once_t ponce_;
};
pthread_once_t Singleton::ponce_ = PTHREAD_ONCE_INIT;
Singleton* Singleton::instance() {
pthread_once(&ponce_, &Singleton::init);
return pInstance;
}
当然,如果使用饿汉模式,可以避免使用锁:
class Singleton
{
public:
static Singleton *pInstance;
static Singleton *getInstance()
{
return pInstance;
}
private:
Singleton(){}
};
在Singleton.cpp中初始化:
Singleton * Singleton::pInstance = new Singleton();
参考文献:
http://www.zkt.name/dan-li-mo-shi-singleton-ji-c-shi-xian/
https://www.jianshu.com/p/d9334d992cbe