一、设计模式大概谈

“设计模式”:代码的一些写法,与常规的写法不太一样,程序灵活,维护起来很方便,但是别人接管、阅读代码很痛苦。

用“设计模式”理念写出来的代码很晦涩。<< head first>>

老外应付特别大的项目时候,把项目开发经验、模块划分经验,总结成设计模式。(现有开发需求,后有理论总结和整理)

设计模式拿到中国来,不太一样,拿着一个程序(项目)往设计模式上套;一个小小的项目,它非要弄几个设计模式上去

设计模式肯定有他独特的有点,要活学活用,不要深陷其中,生搬硬套。

二、单例设计模式

使用频率高。

单例:整个项目中,有某个特殊或某些特殊的类,属于该类的对象,我只能创建1个,多了我就创建不了了。

class MyCAS{//单例类
private:MyCAS() {} //私有化构造函数,就不能用MyCAS a;这种方式来创建对象了static MyCAS* m_instance;//静态成员变量
public:static MyCAS* GetInstance(){if(m_instance == NULL){m_instance = new MyCAS();static CGARhuishou cl;}return m_instance;}void func() {cout << "测试" << endl;}class CGARhuishou{//类中套类,用来释放对象public:~CGARhuishou(){if(MyCAS::m_instance){//如果这个m_instance不是空,那么就得释放MyCAS对象delete MyCAS::m_instance;MyCAS::m_instance = NULL;}}}};//静态变量初始化
MyCAS* MyCAS::m_instance=NULL;MyCAS *p_a = MyCAS::GetInstance();//第一次调用函数,返回m_instance就非空了,当再次创建就不行了。
MyCAS *p_b = MyCAS::GetInstance();
p_a->func();
MyCAS::GetInstance()-func();

三、单例设计模式共享数据问题分析、解决

有时候需要在我们自己创建的线程(不是主线程)中创建A这个单例类的对象,这种线程可能最少2个。我们可能会面临

GetInstance()这个成员函数要互斥,例如:

#include <iostream>
#include <thread>
#include <mutex>using namespace std;
std::mutex resource_mutex;class MyCAS{//单例类
private:MyCAS() {} //私有化构造函数,就不能用MyCAS a;这种方式来创建对象了static MyCAS* m_instance;//静态成员变量
public:static MyCAS* GetInstance(){std::unique_lock<std::mutex> mymutex(resource_mutex);//会自动加锁if(m_instance == NULL){m_instance = new MyCAS();static CGARhuishou cl;}return m_instance;}void func() {cout << "测试" << endl;}class CGARhuishou{//类中套类,用来释放对象public:~CGARhuishou(){if(MyCAS::m_instance){//如果这个m_instance不是空,那么就得释放MyCAS对象delete MyCAS::m_instance;MyCAS::m_instance=NULL;}}};};//静态变量初始化
MyCAS* MyCAS::m_instance=NULL;//线程入口函数
void mythread(){cout << "我的线程开始执行了" <<endl;MyCAS* p_a = MyCAS::GetInstance();//这里会出问题p_a->func();cout << "我的线程执行完毕了" << endl;return;
}int main(){std::thread thread1(mythread);std::thread thread2(mythread);thread1.join();thread2.join();return 0;}

两个线程的入口函数是相通的,有一种情况可能会发生:当thread1正好创建A对象(正在执行GetInstance)的时候任务被切换到了thread2,那么thread2也会同时执行到GetInstance,相当于两个线程同时执行这个函数,这就坏事了。所以要来一个锁,就行了。

上面的效率太低了,相当于每次创建A都要调用get函数,还要锁上,相当于你这么复杂的步骤,只是为了解决初始化时的问题,这几很低效率了。

怎样高效解决呢?看下面代码:

static MyCAS* GetInstance(){     //双重锁定提高效率                                                                   if(m_instance==NULL)//双重锁定,双重检查                                             {                                                                                    //这段函数也就是只执行一次                                     std::unique_lock<std::mutex> mymutex(resource_mutex);//会自动加锁            if(m_instance == NULL){    m_instance = new A();                                                        static huishou cl;                                                           }            }                                                                                    return m_instance;
} 

如何提高效率的?

(1)我们知道如果if(m_instance!=NULL)条件成立,表示肯定已m_instance已经被new过了;

(2)如果if(m_instance==NULL),不代表m_instance一定没有被new过,比如上面说的那种特殊情况。

第一个if条件成功的情况就是第一次创建A对象或者几个线程同时第一次创建A对象的手,才会进入第一个if执行语句中,然后就加锁。一旦这个对象已经创建了,那么第一个if里面的执行语句就根本不会再执行了了。也即是说,第一个if就专门是针对出创A对象或多个线程初创A对象的情况,一旦A对象有了,就再也不会执行里面的语句了,效率高了很多。

四、std::call_once():c++11引入的函数,该函数的第二个参数是一个函数名a()

call_once功能是能够保证函数a()只被调用一次。

call_once具备互斥量这种能力,而且效率上,比互斥量消耗的资源更少

call_once()需要一个标记结合使用,这个标记std::once_flag;其实once_flag是一个结构

call_once()就是通过这个标记来巨鼎对应的函数a()是否执行,调用call_once成功后,call_once()就把这个标记设置为一种已调

后续再次调用call_once(),只要once_flag被设置为了“已调用”状态,那么对应的函数a()就不会在被执行了;

#include <iostream>
#include <mutex>
#include <thread>using namespace std;
std::once_flag g_flag;//系统定义的标记class MyCAS{//单例类static void CreateInstance(){//只被调用一次,不加说明都默认成是privatestd::chrono::milliseconds dura(20000); // 休息20秒std::this_thread::sleep_for(dura);cout << "CreateInstance()被执行了" << endl;m_instance = new MyCAS();static CGARhuishou cl;}private:MyCAS() {} //私有化构造函数,就不能用MyCAS a;这种方式来创建对象了static MyCAS* m_instance;//静态成员变量public:static MyCAS* GetInstance(){//如果两个线程同时执行到这里,其中一个线程要等另外一个线程执行完毕CreateInstance()std::call_once(g_flag,CreateInstance);return m_instance;}void func() {cout << "测试" << endl;}class CGARhuishou{//类中套类,用来释放对象public:~CGARhuishou(){if(MyCAS::m_instance){//如果这个m_instance不是空,那么就得释放MyCAS对象delete MyCAS::m_instance;MyCAS::m_instance=NULL;}}};};//静态变量初始化
MyCAS* MyCAS::m_instance = NULL;//线程入口函数
void mythread(){cout << "我的线程开始执行了" <<endl;MyCAS* p_a = MyCAS::GetInstance();//这里会出问题p_a->func();cout << "我的线程执行完毕了" << endl;return;
}int main(){std::thread thread1(mythread);std::thread thread2(mythread);thread1.join();thread2.join();return 0;}

如图所示call_once的CreateInstance只被执行一次

单例设计模式共享数据分析、解决,call_once相关推荐

  1. 单例设计模式和多线程

    单例设计模式 单例:整个项目中,有某个类或者某些特殊的类,属于该类的对象只能建立一个. #include<iostream> using namespace std;class MyCAS ...

  2. 【Java】day9--main方法、单例设计模式、继承、方法重写部分知识点总结

    (一)main方法 jvm调用main方法,jvm也是一个程序     main方法详解:         public:公共  保证该类在任何情况下,jvm都对其方法可见.         stat ...

  3. java day07第七课静态的和单例设计模式

    静态的(static)和单例模式 main函数 主函数是一个特殊的函数,作为程序的入口,可以被jvm调用 主函数的定义 public 表示该函数的访问权限是最大的. static 代表主函数随着类的加 ...

  4. 设计模式之单例设计模式(懒汉式)

    package july.star.thread22; /*** Teacher* 饿汉式:类一加载就加载* 懒汉式:需要时才加载* 面试题:单例模式的思想是什么,请用代码体现.* 开发:饿汉式(不会 ...

  5. 菜鸟之路-浅谈设计模式之单例设计模式

    单例设计模式 定义:确保一个类仅仅有一个实例,并且自行实例化并向整个系统提供这个实例. 单例模式是一种经常使用的软件设计模式.在它的核心结构中仅仅包括一个被称为单例的特殊类. 通过单例模式能够保证系统 ...

  6. GOF设计模式之1:单例设计模式

    1.单例设计模式核心作用: 保证一个类只有一个实例,并且提供了访问该实例的全局访问点 2.常见应用场景: window的任务管理器 项目中读取配置文件一般也是一个单例模式 数据库连接池的设计也是采用单 ...

  7. 23种设计模式:单例设计模式(饿汉式 VS 懒汉式)

    23种设计模式:单例设计模式(饿汉式 VS 懒汉式) 每博一文案 世事浮沉,有太多的责任需要我们担当,生活中总有些挫折和磨难,让我们觉得快要杠不住了. 但当我们咬牙坚持过那段难熬的时光后,发现并没有想 ...

  8. 设计模式之简单单例设计模式

    参考资料:[作者:刘伟  http://blog.csdn.net/lovelion] 单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例 ...

  9. JavaSE面向对象:继承、多态、Super、Object类、重写、static、final、静态成员、懒汉式、饿汉式、单例设计模式、初始化块、抽象类、抽象方法、接口

    感谢尚硅谷免费提供的视频 继承 ** 理解 ** 生活中的继承:子女继承了父母的财产或相貌或才华 java中的继承:一个类不用自己定义属性或方法,就已经具备了另一个类的属性和方法 把这种现象称为jav ...

最新文章

  1. mysql duplicate jpa_SpringBoot Jpa 双数据源mysql + oracle + liquibase+参考源码
  2. 零基础可以学python吗-初学者必知:零基础学习Python真的能学会吗?
  3. Yii2语言国际化配置
  4. 书脊开胶了用什么胶粘_鞋子开胶还傻傻用502粘?劝你别做无用功,用这笨招天天穿新鞋...
  5. 在受了老板的委屈时候写下的
  6. 付费?广告?捐款?如何让开源软件活下去?
  7. Unity3D(三)材质
  8. jetty的安装,优化
  9. SHELL 读取文件的每一行内容并输出
  10. 完稿—单片机原理与接口技术
  11. 套路得人心之我的运营之路!(文末有福利)
  12. 云服务器搭建MQTT服务器
  13. php乘法表颜色渐变图片,用标准标签库写的九九乘法表(带渐变颜色)
  14. win7所有服务被禁用(应该是大多数被禁用)
  15. 如何让RS485总线挂接更多数量的设备?
  16. XPO:Session管理与缓存--测试篇
  17. 微信小程序显示当前时间
  18. 解决Win7笔记本下玩游戏的显示问题
  19. 预制菜开启春节之战,破局立新正在进行时
  20. python创建函数、可以接受任意多个整数参数并求和_如何实现Python函数的参数不限个数?...

热门文章

  1. gradle:Creating New Gradle Builds
  2. 使用 WinSCP 连接到 VCSA 6.5 失败并显示以下错误:收到的 SFTP 数据包过大
  3. Oracle管理监控之sql developer配置与简单使用
  4. Ora-00600 错误的代码含义及常用查询
  5. ubuntu下Pure-FTPd的安装和配置
  6. linux通过rpm和yum安装包
  7. AutoCAD使用技巧
  8. c/c++头文件之string.h、cstring与string的区别
  9. 网站Banner图切换效果(flash)
  10. 【转载】ubuntu换源