目录
- 单例模式
- 懒汉模式
- 饿汉模式
- 线程安全的懒汉模式
- 双重检查锁定(过时,错误的版本)
- C++11 特有的线程安全懒汉模式
单例模式
单例模式可以说是23种设计模式中最为简单的一种设计模式
- 类中只有唯一一个实例并且是私有化的,只能通过公有的静态函数获取,并且构造函数私有化,防止被外部实例化
- 提供静态的公有函数用来获取访问唯一的一个实例
如果说类中的某一个资源是属于类本身的,而不是所属类的某一个对象的,我们就可以把这个资源设置为static, 类比来说,如果某一个类的成员都是所属于类本身,并且要公共使用的话,我们就可以把这个类设置为单例模式,并且提供唯一的static实例 公共使用
使用场景:常用于数据库类,日志类的实现
最简单的单例模式类:
class single{private://私有静态指针变量指向唯一实例static single *p;//私有化构造函数single(){}~single(){}public://公有静态方法获取实例static single* getinstance();
};
懒汉模式
单例模式类中有唯一一个实例的指针,懒汉模式,即第一次使用时才初始化这个单例模式的指针
class single{private://私有静态指针变量指向唯一实例static single *p;//私有化构造函数single(){}~single(){}public://公有静态方法获取实例static single* getinstance();
};single* single::p = NULL;
single* single::getinstance(){if (NULL == p){p = new single; }return p;
}
在调用getinstance函数获取唯一实例的时候才进行第一次初始化.
饿汉模式
饿汉模式顾名思义非常饿,它是在程序一开始的时候,就对唯一的实例初始化了
class single{private://私有静态指针变量指向唯一实例static single *p;//私有化构造函数single(){}~single(){}public://公有静态方法获取实例static single* getinstance();
};
single* single::p = new single();
single* single::getinstance(){return p;
}
线程安全的懒汉模式
之前的懒汉模式并没有提到多线程安全的情况,如果现在有多个线程使用单例模式类,就有可能会导致多个线程对该实例的多次初始化,这就产生错误了,接下来给出线程安全版本
双重检查锁定(过时,错误的版本)
class single{private://私有静态指针变量指向唯一实例static single *p;static pthread_mutex_t lock;//定义一个互斥锁//私有化构造函数single(){pthread_mutex_init(&lock, NULL);}~single(){}public://公有静态方法获取实例static single* getinstance();
};pthread_mutex_t single::lock;single* single::p = NULL;
single* single::getinstance(){if (NULL == p){pthread_mutex_lock(&lock);if (NULL == p){p = new single;}pthread_mutex_unlock(&lock);}return p;
}
这种保证线程安全的方式叫做双重检查锁定,使用互斥锁对new进行保护,又为了防止每次调用函数时都需要加锁,在锁的外围又加了一层 if判断,但是这种做法后来被证实是错误的,并不能完全保证线程安全
详细参考Scott Meyers 与 Andrei Alexandrescu 的“C++ and the Perils of Double-Checked Locking”这篇文章
C++11 特有的线程安全懒汉模式
class single{private:single(){}~single(){}public:static single* getinstance();};single* single::getinstance(){static single obj;return &obj;
}
这种方式不需要加互斥锁,也能保护线程安全,算是最好的一种实现方式.
class single{private:single(){}~single(){}void my_print_private(){ cout<<"helloworld"<<endl;}public:static single* getinstance();static void my_print_public() //这里也可以改成不是static,函数体直接调用my_print_private即可{single::getinstance()->my_print_private();}};single* single::getinstance(){static single obj;return &obj;
}