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

服务器做网站用什么环境好谷歌推广app

服务器做网站用什么环境好,谷歌推广app,城市建设单招网站,贵阳网站推广文章目录实现 1:静态成员实现 2:atexit 懒汉模式实现 3:原子变量 懒汉模式实现4:atexit 饿汉模式* 实现5:magic static单例模式:保证一个类仅有一个实例,并提供一个该实例的全局访问点。 稳…

文章目录

      • 实现 1:静态成员
      • 实现 2:atexit + 懒汉模式
      • 实现 3:原子变量 + 懒汉模式
      • 实现4:atexit + 饿汉模式
      • * 实现5:magic static

单例模式:保证一个类仅有一个实例,并提供一个该实例的全局访问点。

  • 稳定点:类只有一个实例,提供全局
  • 变化点:有多个类都是单例,能否复用代码

实现 1:静态成员

  • 构造函数和析构函数私有化
  • 禁掉拷贝构造、拷贝赋值、移动构造、移动赋值
  • 静态成员函数
  • 静态私有成员

前两点针对唯一实例,后两点针对全局访问。

问题:当程序结束后,不会调用析构函数,堆上资源无法释放,内存泄漏。虽然程序结束后,堆上所有的数据被销毁,但是无法保存需要持久化的数据。

class Singleton {
public:// 静态成员函数:全局访问点static Singleton* getInstance() {if(nullptr == _pInstance) {_pInstance = new Singleton();}return _pInstance;}private:// 构造函数和析构函数私有化Singleton(); ~Singleton(); // 禁掉拷贝构造、拷贝赋值、移动构造、移动赋值Singleton(const Singleton &) = delete;Singleton& operator=(const Singleton&) = delete;Singleton(Singleton &&) = delete;Singleton& operator=(Singleton &&) = delete;private:// 静态成员:静态成员函数只能访问静态成员static Singleton* _pInstance;};// 静态成员需要初始化
Singleton* Singleton::_instance = nullptr; 

实现 2:atexit + 懒汉模式

atexit 函数:在进程结束后利用回调函数自动释放堆空间。

/* 
功能:注册给定函数,并在进程结束后调用该函数
参数:函数指针,指向被调用的函数(返回值、参数均为void) 
*/
#include <stdlib.h>
int atexit(void (*function)(void));

利用这一特性,在进程结束时 atexit 函数调用销毁函数,完成析构工作。

问题:atexit 函数本身安全,但是多线程环境下。存在线程安全问题。

static Singleton* getInstance() {if(nullptr == _pInstance) {// 问题:多个并发线程可能同时创建对象_pInstance = new Singleton();atexit(Singleton::Destructor);}return _pInstance;
}

为保证线程安全,需要加锁。对于加锁操作,只有第一次写操作创建对象的时候,需要加锁;其他时候都是读操作,没有必要加锁。因此这里在实现的时候可以采用双重检测 double check的技巧。

#include <stdlib.h>
class Singleton {
public:static Singleton* getInstance() {if(nullptr == _pInstance) {_pInstance = new Singleton();// 线程安全,双重检测:double check      if (nullptr == _pInstance) {std::lock_guard<std::mutex> lock(_mutex);if (nullptr == _pInstance) {// 问题:多线程环境下,cpu reorder_pInstance = new Singleton();atexit(Singleton::Destructor);}}return _pInstance;// 注册回调函数,进程结束后,调用销毁函数atexit(Singleton::Destructor);}return _pInstance;}private:Singleton(); ~Singleton(); Singleton(const Singleton &) = delete;Singleton& operator=(const Singleton&) = delete;Singleton(Singleton &&) = delete;Singleton& operator=(Singleton &&) = delete;// 注册销毁函数为atexit的回调函数,用于在进程结束后释放堆空间static void Destructor() {if (nullptr != _instance) { delete _instance;_instance = nullptr;}}private:static Singleton* _pInstance;};Singleton* Singleton::_instance = nullptr; 

问题:new 操作符指令重排

C++ 98 表达单线程语义。而在多核多线程的情况下,若 cpu 指令重排,例如:对于 new 运算符的指令执行:分配内存、调用构造函数、返回指针。若发生 cpu 指令重排,会优化为分配内存、返回指针,却还没有调用构造函数初始化数据。此时,若有其他线程访问,可能造成程序的崩溃。

实现 3:原子变量 + 懒汉模式

C++ 11:多线程语义,cpu 指令重排,提供同步原语:原子变量、内存屏障等

原子变量解决

  • 原子性问题
  • 可见性问题:load 可以看见其他线程最新操作的数据, store 修改数据让其他线程可见
  • 执行序问题:memory_order_acuire不能重排指令,memory_order_release松散指令,可以重排指令。

内存屏障(内存栅栏)解决

  • 可见性问题
  • 执行序问题

使用原子变量解决原子性、可见性、执行序

class Singleton {
public:static Singleton * GetInstance() {Singleton* tmp = _instance.load(std::memory_order_acquire);if (tmp == nullptr) {std::lock_guard<std::mutex> lock(_mutex);tmp = _instance.load(std::memory_order_acquire);if (tmp == nullptr) {tmp = new Singleton;_instance.store(tmp, memory_order_release);atexit(Destructor);}}return tmp;}
...static std::atomic<Singleton*> _instance;static std::mutex _mutex;
};
std::atomic<Singleton*> Singleton::_instance; // 静态成员需要初始化
std::mutex Singleton::_mutex; 			     // 互斥锁初始化 

改进:若构造函数中存在其他原子性操作,则可以使用松散的指令执行方式,提升运行速度。使用内存屏障,避免 tmp 指针在 new 操作未执行完就返回给用户。

  • 原子变量解决:原子性、可见性
  • 内存栅栏解决:执行序
class Singleton {
public:static Singleton * GetInstance() {Singleton* tmp = _instance.load(std::memory_order_relaxed);// 获取内存屏障std::atomic_thread_fence(std::memory_order_acquire);if (tmp == nullptr) {std::lock_guard<std::mutex> lock(_mutex);tmp = _instance.load(std::memory_order_relaxed);if (tmp == nullptr) {tmp = new Singleton;// 释放内存屏障std::atomic_thread_fence(std::memory_order_release);_instance.store(tmp, std::memory_order_relaxed);atexit(Destructor);}}return tmp;}...static std::atomic<Singleton*> _instance;static std::mutex _mutex;
};
std::atomic<Singleton*> Singleton::_instance; // 静态成员需要初始化
std::mutex Singleton::_mutex; 			     // 互斥锁初始化 

问题:代码复杂,书写困难。

实现4:atexit + 饿汉模式

懒汉模式是延迟加载,饿汉模式是提前加载。当系统开始运行,加载类的时候就初始化类实例,其他线程无法再创建实例,实现线程安全。

class Singleton {
public:static Singleton* Singleton::getInstance() {if(nullptr == _pInstance) {_pInstance = new Singleton();atexit(Singleton::Destructor);}return _pInstance;}   
...
};// 全局初始化,使其在进程创建之前就不为空,防止子进程创建对象
Singleton* Singleton::_instance = getInstance();

问题:无论是否需要该类实例,都必须提前创建。

* 实现5:magic static

源自:C++ effective,C++ 11 magic static 特性,参考官方文档:静态局部变量,推荐使用。

  • 如果变量在初始化的时候,并发同时进入声明语句,并发线程会阻塞等待初始化结束。线程安全。
  • 静态局部变量首次经过它的声明才会被初始化,在其后所有的调用中,声明都会被跳过。

因此,使用定义在栈上的局部静态变量保存单例对象,具备所有优点:

  • 延迟加载
  • 系统自动调用析构函数,回收内存
  • 没有 new 操作带来的 cpu reorder 操作
  • 线程安全
class Singleton {
public:static Singleton& GetInstance() {// magic static// 定义在栈上的局部静态变量,进程结束后自动释放static Singleton instance;return instance;}private:Singleton(); ~Singleton(); Singleton(const Singleton &) = delete;Singleton& operator=(const Singleton&) = delete;Singleton(Singleton &&) = delete;Singleton& operator=(Singleton &&) = delete;
};
http://www.hkea.cn/news/682257/

相关文章:

  • 网站后台上传图片失败百度下载免费安装最新版
  • 镇江做网站需要多少钱企业网站模板设计
  • 西安seo优化系统网页seo
  • 如何用网站模板做网站广州网络营销推广
  • 承德手机网站建设seo推广排名
  • wordpress块引用一个网站可以优化多少关键词
  • 360网站卖东西怎么做的无锡seo优化公司
  • 邢台人民网站百度视频推广怎么收费
  • 常州天启建设公司网站高端快速建站
  • ppt模板免费下载网站不用登录seo测试工具
  • 四川建设人才网官网查询阜新网站seo
  • 太原网站开发定制百度网盘官网下载
  • 业主装修日记那个网站做的好片多多可以免费看电视剧吗
  • 租车网站建设站长之家源码
  • 昌吉州回族自治州建设局网站地产渠道12种拓客方式
  • 北京市网站公司网络项目免费的资源网
  • 电子商务网站规划、电子商务网站建设站长工具 忘忧草
  • 凡科建网关键词优化公司哪家好
  • seo排名推广工具seo公司多少钱
  • 做视频网站赚钱怎么在百度上推广自己的公司信息
  • 网站建设凡科厦门网站建设平台
  • 互联网行业pest分析福州百度快速优化排名
  • 做网站的接私活犯法吗如何对网站进行推广
  • 身高差效果图网站优化师和运营区别
  • 谷歌wordpress建站搜索引擎算法
  • .net 购物网站开发源代码发布信息的免费平台
  • 自己做一网站大学生网络营销策划书
  • 关于网站建设的文章百度域名收录提交入口
  • 国人在线做网站推广图片大全
  • 郑州网站建设七彩科技四年级说新闻2023