当前位置: 首页 > news >正文

山东网站域名备案时间滁州医院网站建设费用

山东网站域名备案时间,滁州医院网站建设费用,服务平台入口,坡头网站建设公司单例模式是什么 在一个项目中#xff0c;全局范围内#xff0c;某个类的实例有且仅有一个#xff08;只能new一次#xff09;#xff0c;通过这个唯一的实例向其他模块提供数据的全局访问#xff0c;这种模式就叫单例模式。单例模式的典型应用就是任务队列。 为什么要使…单例模式是什么 在一个项目中全局范围内某个类的实例有且仅有一个只能new一次通过这个唯一的实例向其他模块提供数据的全局访问这种模式就叫单例模式。单例模式的典型应用就是任务队列。 为什么要使用单例模式 单例模式充当的就是一个全局变量为什么不直接使用全局变量呢因为全局变量破坏类的封装而且不受保护访问不受限制。 饿汉模式 饿汉模式是在类加载时进行实例化的。 #includeiostream using namespace std;class TaskQueue { public:TaskQueue(const TaskQueue obj) delete;//禁用拷贝构造TaskQueue operator (const TaskQueue obj) delete;//禁用赋值构造static TaskQueue* getInstance() //获取单例的方法{cout 我是一个饿汉模式单例 endl;return m_taskQ;}private:TaskQueue() default; //无参构造static TaskQueue* m_taskQ; //静态成员需要在类外定义 }; TaskQueue* TaskQueue::m_taskQ new TaskQueue;//new一个实例int main() {TaskQueue* obj TaskQueue::getInstance(); }懒汉模式 懒汉模式是在需要使用的时候再进行实例化 #includeiostream using namespace std;class TaskQueue { public:TaskQueue(const TaskQueue obj) delete;//禁用拷贝构造TaskQueue operator (const TaskQueue obj) delete;//禁用赋值构造static TaskQueue* getInstance() //获取单例的方法{if (nullptr m_taskQ){m_taskQ new TaskQueue;}return m_taskQ;}private:TaskQueue() default; //无参构造static TaskQueue* m_taskQ; //静态成员需要在类外定义 }; TaskQueue* TaskQueue::m_taskQ nullptr;int main() {TaskQueue* obj TaskQueue::getInstance(); }在调用**getInstance()**函数获取单例对象的时候如果在单线程情况下是没有什么问题的如果是多个线程调用这个函数去访问单例对象就有问题了。假设有三个线程同时执行了getInstance()函数在这个函数内部每个线程都会new出一个实例对象。此时这个任务队列类的实例对象不是一个而是3个很显然这与单例模式的定义是相悖的。 线程安全问题 对于饿汉模式来说是没有线程安全问题的在这种模式下访问单例对象时这个对象已经被创建出来了要解决懒汉模式的线程安全问题最常用的解决方案就是使用互斥锁可以将创建单例对象的代码使用互斥锁锁住 #includeiostream #includemutex using namespace std;class TaskQueue { public:TaskQueue(const TaskQueue obj) delete;//禁用拷贝构造TaskQueue operator (const TaskQueue obj) delete;//禁用赋值构造static TaskQueue* getInstance() //获取单例的方法{m_mutex.lock();if (nullptr m_taskQ){cout 我加了互斥锁 endl;m_taskQ new TaskQueue;}m_mutex.unlock();return m_taskQ;}private:TaskQueue() default; //无参构造static TaskQueue* m_taskQ; //静态成员需要在类外定义static mutex m_mutex; //定义为静态的因为静态函数只能使用静态变量 }; mutex TaskQueue::m_mutex; TaskQueue* TaskQueue::m_taskQ nullptr;int main() {TaskQueue* obj TaskQueue::getInstance(); }在上面代码的10~13 行这个代码块被互斥锁锁住了也就意味着不论有多少个线程同时执行这个代码块的线程只能是一个相当于是严重限行了在重负载情况下可能导致响应缓慢。我们可以将代码再优化一下 #includeiostream #includemutex using namespace std;class TaskQueue { public:TaskQueue(const TaskQueue obj) delete;//禁用拷贝构造TaskQueue operator (const TaskQueue obj) delete;//禁用赋值构造static TaskQueue* getInstance() //获取单例的方法{if (nullptr m_taskQ){m_mutex.lock();if (nullptr m_taskQ){cout 我加了互斥锁 endl;m_taskQ new TaskQueue;}m_mutex.unlock();}return m_taskQ;}private:TaskQueue() default; //无参构造static TaskQueue* m_taskQ; //静态成员需要在类外定义static mutex m_mutex; }; mutex TaskQueue::m_mutex; TaskQueue* TaskQueue::m_taskQ nullptr;int main() {TaskQueue* obj TaskQueue::getInstance(); }双重检查锁定问题 #includeiostream #includemutex #includeatomic using namespace std;class TaskQueue { public:TaskQueue(const TaskQueue obj) delete;//禁用拷贝构造TaskQueue operator (const TaskQueue obj) delete;//禁用赋值构造static TaskQueue* getInstance() //获取单例的方法{TaskQueue* taskQ m_taskQ.load(); //取出来单例的值if (nullptr taskQ){m_mutex.lock();taskQ m_taskQ.load();if (nullptr taskQ){cout 我加了原子 endl;taskQ new TaskQueue;m_taskQ.store(taskQ); //保存到原子变量中}m_mutex.unlock();}return m_taskQ.load();}private:TaskQueue() default; //无参构造static atomicTaskQueue*m_taskQ; //定义为原子变量static mutex m_mutex; }; mutex TaskQueue::m_mutex; atomicTaskQueue* TaskQueue::m_taskQ;int main() {TaskQueue* obj TaskQueue::getInstance(); }对于m_taskQ new TaskQueue这行代码来说我们期望的执行机器指令执行顺序是 1分配用来保存TaskQueue对象的内存 2在分配好的内存中构造一个TaskQueue对象即初始化内存 3使用m_taskQ指针指向分配的内存。 但是对多线程来说机器指令可能会被重新排列即 1分配内存用于保存 TaskQueue 对象。 2使用 m_taskQ 指针指向分配的内存。 3在分配的内存中构造一个 TaskQueue 对象初始化内存。 这样重排序并不影响单线程的执行结果但是在多线程中就会出问题。如果线程A按照第二种顺序执行机器指令执行完前两步之后失去CPU时间片被挂起了此时线程B在第3行处进行指针判断的时候m_taskQ 指针是不为空的但这个指针指向的内存却没有被初始化最后线程 B 使用了一个没有被初始化的队列对象就出问题了出现这种情况是概率问题需要反复的大量测试问题才可能会出现。 在C11中引入了原子变量atomic通过原子变量可以实现一种更安全的懒汉模式的单例代码如下 #includeiostream #includemutex #includeatomic using namespace std;class TaskQueue { public:TaskQueue(const TaskQueue obj) delete;//禁用拷贝构造TaskQueue operator (const TaskQueue obj) delete;//禁用赋值构造static TaskQueue* getInstance() //获取单例的方法{TaskQueue* taskQ m_taskQ.load(); //取出来单例的值if (nullptr taskQ){m_mutex.lock();taskQ m_taskQ.load();if (nullptr taskQ){cout 我加了原子 endl;taskQ new TaskQueue;m_taskQ.store(taskQ); //保存到原子变量中}m_mutex.unlock();}return m_taskQ.load();}private:TaskQueue() default; //无参构造static atomicTaskQueue*m_taskQ; //定义为原子变量static mutex m_mutex; }; mutex TaskQueue::m_mutex; atomicTaskQueue* TaskQueue::m_taskQ;int main() {TaskQueue* obj TaskQueue::getInstance(); }使用局部静态 c11新特性有如下规定如果指令逻辑进入一个未被初始化的声明标量所有并发执行应当等待该变量完成初始化。 #includeiostreamusing namespace std;class TaskQueue { public:TaskQueue(const TaskQueue obj) delete;//禁用拷贝构造TaskQueue operator (const TaskQueue obj) delete;//禁用赋值构造static TaskQueue* getInstance() //获取单例的方法{static TaskQueue m_taskQ; //未被初始化return m_taskQ;}void print(){cout hello, world!!! endl;}private:TaskQueue() default; //无参构造 };int main() {TaskQueue* obj TaskQueue::getInstance();obj-print(); }饿汉模式和懒汉模式的区别 懒汉模式的缺点是在创建实例对象的时候有安全问题但这样可以减少内存的浪费如果用不到就不去申请内存了。饿汉模式则相反在我们不需要这个实例对象的时候它已经被创建出来占用了一块内存。对于现在的计算机而言内存容量都是足够大的这个缺陷可以被无视。
http://www.w-s-a.com/news/853078/

相关文章:

  • 洛阳免费网站建设qq是哪家公司开发的软件
  • 怎么做网站网页wordpress网址导航
  • 专业微信网站建设公司首选公司wordpress自动分类插件
  • 网站设计登录界面怎么做网站突然排名没了
  • wordpress 人物页面seo优化公司信
  • 高端网站建设报价网站建设需要硬件设备
  • 做国际物流在哪些网站找客户营销qq怎么申请
  • 网站做推广百度好还是360好科技厅
  • 网站开发工具排名万户网络建一个网站虽要多少钱
  • 用凡科做的网站要钱吗WordPress城市切换
  • 制作一个门户网站需要多少钱营销型网站特征
  • 手机网站 多html中国建设银行网站包头分行
  • 哪个网站做免费广告好招牌图片效果图设计制作
  • 网站建设优化服务机构苏州市做网站
  • 网站如何优化流程企业网站管理系统视频教程
  • 我想克隆个网站 怎么做贵州住房和城乡建设厅官网
  • 网站建设项目前景上海今天新闻综合频道
  • 做网站推销的如何谈客户wordpress怎么做商城
  • 摄影素材库网站服装页面设计的网站
  • 如何用国外网站做头条做个游戏app的费用大概多少
  • 网站 形象入口页福州网站建设网络公司排名
  • 免费下载教学设计的网站送网站建设管理信息内容审核制度
  • 外贸专业网站的公司百度旗下13个app
  • 物理组简介 网站建设高师院校语言类课程体系改革与建设 教学成果奖申报网站
  • 爱网站无法登录怎么回事手表网
  • 网站建设公司现在还挣钱吗山西手动网站建设推荐平台
  • 重庆建设工程交易信息网站网站制作公司起名
  • 东莞寮步做网站的有吗企业宣传册制作
  • 做网站的软件是哪个上蔡做网站
  • 前后端分离实现网站开发紧急通知网页升级