为什么需要单例模式?

所谓“单例模式”,指的就是一个类只能有一个或者几个实例化的对象——比如说,在 Windows 或者 macOS 这样的桌面操作系统里,鼠标指针箭头有且只有一个,不能出现第二个。
**

懒汉与饿汉

单例分为两种实现方法:

  • 懒汉

第一次用到类实例的时候才会去实例化

  • 饿汉

单例类定义的时候就进行了实例化

懒汉模式代码:

  1. class singleton {
  2. private:
  3. singleton(){}
  4. static singleton *p;
  5. public:
  6. static singleton *instance();
  7. };
  8. singleton *singleton::p =nullptr;
  9. singleton* singleton::instance(){
  10. if(p ==nullptr)
  11. p =new singleton();
  12. return p;
  13. }

饿汉模式代码:(**自己写代码首选这种**)

因为是定义就进行了实例化,所以会造成资源浪费

  1. #include <iostream>
  2. class singleton {
  3. private:
  4. singleton(){
  5. std::cout << "饿汉模式构造函数" << std::endl;
  6. }
  7. static singleton *p;
  8. public:
  9. static singleton *instance(){
  10. return p;
  11. }
  12. void print(){
  13. std::cout << "you did it!" << std::endl;
  14. }
  15. };
  16. singleton *singleton::p = new singleton();
  17. int main()
  18. {
  19. singleton *pp = singleton::instance();
  20. pp->print();
  21. return 0;
  22. }

注: l懒汉模式只适合在单线程下,当多线程时,是不安全的。考虑两个线程同时首次调用instance方法且同时检测到p是nullptr,则两个线程会同时构造一个实例给p,这将违反了单例的准则。**

最终版本 (懒汉模式线程优化)

C++11下的单例模式

  1. mutex singleton::lock_;
  2. atomic<singleton *> singleton::p;
  3. /*
  4. * std::atomic_thread_fence(std::memory_order_acquire);
  5. * std::atomic_thread_fence(std::memory_order_release);
  6. * 这两句话可以保证他们之间的语句不会发生乱序执行。
  7. */
  8. singleton *singleton::instance(){
  9. singleton *tmp = p.load(memory_order_relaxed);
  10. atomic_thread_fence(memory_order_acquire);
  11. if(tmp ==nullptr){
  12. lock_guard<mutex> guard(lock_);
  13. tmp = p.load(memory_order_relaxed);
  14. if(tmp ==nullptr){
  15. tmp =new singleton();
  16. atomic_thread_fence(memory_order_release);
  17. p.store(tmp, memory_order_relaxed);
  18. }
  19. }
  20. return p;
  21. }

如果是在unix平台的话,除了使用atomic operation外,在不适用C++11的情况下,还可以通过pthread_once来实现Singleton。

  1. class singleton {
  2. private:
  3. singleton();//私有构造函数,不允许使用者自己生成对象
  4. singleton(const singleton &other);
  5. //要写成静态方法的原因:类成员函数隐含传递this指针(第一个参数)
  6. staticvoid init(){
  7. p =new singleton();
  8. }
  9. staticpthread_once_t ponce_;
  10. static singleton *p;//静态成员变量
  11. public:
  12. singleton *instance(){
  13. // init函数只会执行一次
  14. pthread_once(&ponce_,&singleton::init);
  15. return p;
  16. }
  17. };

参考:
https://www.bookstack.cn/read/CPlusPlusThings/68fdd6c8536795e6.md