设计模式——单例模式
来源:互联网 发布:淘宝购物一般几天到货 编辑:程序博客网 时间:2024/06/16 06:10
你肯定被面过这样一个问题:C++中如何实现一个类只能实例化一个对象?
单例模式可以保证一个类只能实例化一个对象!单例模式的核心结构中只包含一个被称为单例的特殊类。
防止用户随意的调用构造函数,将类的构造函数写成私有的,给用户提供返回对象的方法,在调用时不能依赖对象。
- 版本一: 懒加载(不论是否使用,都要初始化)
class Singleton{public: static Singleton& getInstance() { return singlenton; }private: Singleton() {}; static Singleton singlenton;};Singleton Singleton::singlenton = Singleton::getInstace() ;//不论是否使用,程序运行后,对象已存在
- 版本二:快加载(使用时候才初始化)
class Singleton{public: static Singleton* getInstance() { if(psingleTon == NULL) { psingleTon = new Singleton(); } return psingleTon; }private: Singleton(){} static Singleton *psingleTon;};Singleton* Singleton::psingleTon = NULL;/快加载int main(){ //需要时调用getInstance方法new对象 psingleTon *p1 = Singleton::getInstance();}
- 版本三:考虑多线程安全问题,使用互斥锁同步
判断是否是线程安全的——是否存在竟态条件(存在竟态条件,非线程安全的)
判断是否存在竟态条件——随着线程调度顺序不同,程序结果是否相同(不相同,存在竟态条件)
存在竟态条件的代码区称为临界区
临界区的代码必须是原子操作
实现原子操作要使用互斥锁
class Singleton{public: static Singleton* getInstance() { //保证多线程下,new对象是原子操作 pthread_mutex_lock(&mutex); if(psingleTon == NULL) { psingleTon = new Singleton(); } pthread_mutex_unlock(&mutex); return psingleTon; }private: Singleton(){} static Singleton *psingleTon;};Singleton* Singleton::psingleTon = NULL;//快加载int main(){ Singleton *p1 = Singleton::getInstance(); Singleton *p2 = Singleton::getInstance();//不new Singleton *p3 = Singleton::getInstance();//不new}
- 版本四:存在单线程和多线程两种情况,解决单线程加锁解锁的效率问题,使用双重if判断
单线程时,只执行一次加锁加锁的情况,其他第一个if语句都为false,直接return。
多线程时,依然考虑线程安全和竟态条件
class Singleton{public: static Singleton* getInstance() { if(NULL == psingleTon)//懒加载 { pthread_mutex_lock(&mutex);//多线程安全问题 if(NULL == psingleTon)//单线程实现效率问题 { psingleTon = new Singleton(); } pthread_mutex_unlock(&mutex); } return psingleTon; }private: Singleton(){} static Singleton *psingleTon;};Singleton* Singleton::psingleTon = NULL;int main(){ Singleton *p1 = Singleton::getInstance();//加锁,new Singleton *p2 = Singleton::getInstance();//直接return Singleton *p3 = Singleton::getInstance();//直接return }
- 版本五 考虑编译器的指令优化和CPU的动态指令优化
volatile,阻止编译器为了提高速度,将变量值缓存到寄存器中,
每次直接从寄存器中取数据
volatile,阻止编译器对指令进行动态换序优化
barrier阻止CPU对指令进行动态换序优化
class Singleton{public: volatile static Singleton* getInstance() { if(NULL == psingleTon)//懒加载 { pthread_mutex_lock(&mutex);//多线程安全问题 if(NULL == psingleTon)//单线程实现效率问题 { psingleTon = new Singleton(); } pthread_mutex_unlock(&mutex); } return psingleTon; }private: Singleton(){} volatile static Singleton *psingleTon;//防止编译器缓存值};volatile Singleton* Singleton::psingleTon = NULL;int main(){ Singleton *p1 = Singleton::getInstance();//加锁,new Singleton *p2 = Singleton::getInstance();//直接return Singleton *p3 = Singleton::getInstance();//直接return }
阅读全文
0 0
- 设计模式—单例设计模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- sdut 1959 简单枚举类型——植物与颜色
- MD5加密
- 卷积神经网络CNN经典模型整理Lenet,Alexnet,Googlenet,VGG,Deep Residual Learning
- H
- elasticsearch安装
- 设计模式——单例模式
- Tomcat配置
- 1.2算法的作用二分思想(猜价格游戏)清屏操作
- 【NOIP2017】SummerTraining0727
- Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介
- CALayer 和 UIView 的区别和联系
- IntelliJ 运行程序前设置运行参数
- vue v-model 动态生成
- NIO(一)——阻塞/非阻塞/同步/异步/NIO/select/epoll基本概念