对于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