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

要给公司做一个网站怎么做的吗网站怎么做 流程图

要给公司做一个网站怎么做的吗,网站怎么做 流程图,个人网站设计提纲,学做川菜最好的网站文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性&#xf…

文章目录

  • 1. 基本概念
  • 2. 设计要点
  • 3. 实现方式
  • 4. 详解懒汉模式

1. 基本概念

线程安全(Thread Safety)

线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性,不会因线程切换导致错误结果。

单例模式(Singleton Pattern)

单例设计模式是一种创建型设计模式,其核心目的是确保一个类只有一个实例存在,并提供全局访问点来获取该实例。它常用于管理全局资源(如配置信息、日志系统、数据库连接池等),避免重复创建和资源竞争。

2. 设计要点

  1. 构造函数和析构函数是私有的,不允许外部生成和释放
    • 禁止外部实例化:外部代码无法通过 new 或直接声明的方式创建对象,确保唯一实例的控制权在类自身。
    • 控制生命周期:析构函数私有化可防止外部意外删除单例对象,保证其生命周期与程序一致。
    • 符合单一职责原则:类的创建和销毁逻辑由自身管理,避免外部干扰。
  2. 静态成员变量和静态返回单例的成员函数
    • 全局访问点:通过静态方法 getInstance() 提供统一的实例获取方式,替代直接访问全局变量。
    • 延迟初始化(懒汉式):仅在首次调用时创建实例,节省资源。
    • 线程安全(需额外处理):可通过锁或局部静态变量(C++11 后)确保多线程安全。
      • 在单例模式中,如果多个线程同时调用 getInstance() 方法,可能导致多次创建实例(如懒汉模式未加锁时),破坏单例的唯一性。
      • 解决方案
        • 加锁(互斥量):在 getInstance() 中使用互斥锁(如 std::mutex)确保线程同步。
        • 局部静态变量(C++11):利用编译器保证局部静态变量的初始化是线程安全的。
        • 饿汉模式:提前初始化实例,避免多线程竞争。
  3. 禁用拷贝构造函数和赋值运算符
    • 防止拷贝:避免通过拷贝构造函数复制单例对象,破坏唯一性。
    • 防止赋值:禁止通过赋值运算符覆盖单例对象,如 instance2 = instance1
    • 强制单例约束:从语法层面杜绝意外破坏单例模式的行为。
要点解决的问题实际意义
私有构造/析构外部随意创建或销毁实例确保实例的唯一性和可控性
静态成员与访问方法全局访问与资源管理提供统一入口,支持延迟初始化与线程安全
禁用拷贝与赋值意外复制导致多实例维护单例的严格唯一性

3. 实现方式

懒汉模式

懒汉模式的核心是延迟初始化(Lazy Initialization),即在首次调用 getInstance() 时才创建单例实例。在此之前,实例未被分配内存。

特点

  • 优点
    • 节省资源:若单例对象未被使用,则不会创建。
    • 适合初始化耗时的对象(如文件系统、网络连接)。
  • 缺点
    • 需处理线程安全问题(多线程下可能重复创建)。
    • 首次访问可能因初始化导致延迟。

饿汉模式

饿汉模式的核心是提前初始化,即在程序启动时(或类加载时)直接创建单例实例,无论是否被使用。

特点

  • 优点
    • 线程安全:实例在程序启动时初始化,避免多线程竞争。
    • 代码简单:无需处理复杂的线程同步逻辑。
  • 缺点
    • 可能浪费资源:即使未使用单例对象,也会占用内存。
    • 初始化时间可能影响程序启动速度。

实现样例

class Singleton {
public:static Singleton* getInstance() {return &instance; // 直接返回已初始化的实例}
private:static Singleton instance;Singleton() {}~Singleton() {}
};
// 程序启动时初始化(饿汉模式)
Singleton Singleton::instance;

对比懒汉模式与饿汉模式

特性懒汉模式饿汉模式
初始化时机首次调用 getInstance()程序启动时(或类加载时)
线程安全需额外处理(如加锁或 C++11 特性)天然线程安全
资源占用按需分配,节省资源提前占用内存,可能浪费资源
适用场景初始化耗时、使用频率不确定的对象初始化简单、使用频繁的对象

实际开发中,推荐使用 C++11 的局部静态变量懒汉模式(Meyers’ Singleton,线程安全且代码简洁),或根据场景选择饿汉模式。

4. 详解懒汉模式

参考:【C++面试题】手撕单例模式_哔哩哔哩_bilibili

样例1

class Singleton1 {
public:// 要点2static Singleton1 * GetInstance() {if(_instance == nullptr) {_instance = new Singleton1();}return _instance;}
private:// 要点1Singleton1() {}~Singleton1() {std::cout << "~Singleton1()\n";}// 要点3Singleton1(const Singleton1 &) = delete;Singleton1& operator = (const Singleton1&) = delete;Singleton1(Singleton1 &&) = delete;Singleton1& operator = (Singleton1 &&) = delete;// 要点2static Singleton1 *_instance; 
};
Singleton1* Singleton1::_instance = nullptr;

存在错误:

  • 该类创建的单例对象在堆中,虽然资源会被释放,但其在释放的时候是无法调用析构函数的。
  • 非线程安全

样例2

class Singleton2 {
public:static Singleton2 * GetInstance() {if(_instance == nullpte) {_instance = new Singleton2();atexit(Destructor);}return _instance;}
private:static void Destructor() {if(nullptr != _instance) {delete _instance;_instance = nullptr;}}Singleton2() {}~Singleton2() {std::cout << "~Singleton2()\n";}Singleton2(const Singleton2 &) = delete;Singleton2& operator = (const Singleton2&) = delete;Singleton2(Singleton2 &&) = delete;Singleton2& operator = (Singleton2 &&) = delete;static Singleton2 *_instance; 
};
Singleton2* Singleton2::_instance = nullptr;

针对样例1的问题,添加atexit(),在程序结束时手动释放对象,从而调用析构函数

存在问题:

  • 非线程安全

样例3

class Singleton3 {
public:static Singleton3 * GetInstance() {std::lock_guard<std::mutex> lock(_mutex);if(_instance == nullptr) {std::lock_guard<std::mutex> lock(_mutex);if(_instance == nullptr) {_instance = new Singleton3();// 1. 分配内存// 2. 调用构造函数// 3. 返回对象指针 atexit(Destructor);}}return _instance;}
private:static void Destructor() {if(nullptr != _instance) {delete _instance;_instance = nullptr;}}Singleton3() {}~Singleton3() {std::cout << "~Singleton3()\n";}Singleton3(const Singleton3 &) = delete;Singleton3& operator = (const Singleton3&) = delete;Singleton3(Singleton3 &&) = delete;Singleton3& operator = (Singleton3 &&) = delete;static Singleton3 *_instance; static std::mutex _mutex;
};
Singleton3* Singleton3::_instance = nullptr;
std::mutex Singleton3::_mutex;

在创建实例对象是使用互斥锁来实现线程安全

  • 单检测

    先加锁,再判断是否需要创建对象;

    该方法只需要检测一次,但是在已经创建对象的情况下,只需要检测然后返回就行,不需要再第一次检测前加锁(力度过大,效率低)

  • 双检测(Double-Checked Locking,DCL)

    先做第一次检测,然后在需要创建对象时才加锁,此时多线程程序会出现多个线程同时通过一次检测到创建对象的代码块,所以需要第二次检测对象是否创建来避免重复创建

存在问题

在多线程程序中,CPU会进行指令重排,如new操作的正常顺序应该是(1-2-3),在指令重排之后执行顺会变为(1-3-2)。此时如果某个线程执行到new的“返回对象指针操作”,而另外一个线程执行到第一次检测,则会出现另外一个线程返回为初始化对象的情况。


样例4:(面试八股的重点

class Singleton4 {
public:static Singleton4 * GetInstance() {Singleton4* 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 Singleton4();std::atomic_thread_fence(std::memory_order_release);_instance.store(tmp, std::memory_order_relaxed);atexit(Destructor);}}return tmp;}
private:static void Destructor() {Singleton4* tmp = _instance.load(std::memory_order_relaxed);if(nullptr != tmp) {delete tmp;}}Singleton4() {}~Singleton4() {std::cout << "~Singleton4()\n";}Singleton4(const Singleton4 &) = delete;Singleton4& operator = (const Singleton4&) = delete;Singleton4(Singleton4 &&) = delete;Singleton4& operator = (Singleton4 &&) = delete;static std::atomic<Singleton4*> _instance;static std::mutex _mutex;
};
std::atomic<Singleton4*> Singleton4::_instance;
std::mutex Singleton4::_mutex;

使用内存屏障和原子操作来解决指令重排的问题

内存屏障

  • 作用
    强制限制指令重排,并确保内存操作的可见性(即一个线程的写入对其他线程立即可见)。
  • 类型
    • 获取屏障(acquire fence)
      后续读/写操作不会重排到屏障前,且能读取其他线程的释放操作结果。
    • 释放屏障(release fence)
      前面的读/写操作不会重排到屏障后,且保证当前线程的写入对其他线程可见。
  • 代码中的应用
    • 获取屏障:确保 if(tmp == nullptr) 之后的代码能看到其他线程的完整初始化结果。
    • 释放屏障:确保 new 的构造操作完成后,再存储指针到 _instance

原子操作

  • 定义
    不可分割的操作,保证对变量的读写要么完全执行,要么不执行,不会出现中间状态。
  • 内存顺序(Memory Order)
    • memory_order_relaxed:仅保证原子性,无同步或顺序约束(允许指令重排)。
    • memory_order_acquire/release:与屏障配合,实现同步语义。
  • 代码中的应用
    _instance 被声明为 std::atomic<Singleton4*>,确保其读写是原子的,避免数据竞争。

原子操作详情参考:C++八股 —— 原子操作-CSDN博客


样例5

class Singleton5 {
public:static Singleton5* GetInstance() {static Singleton5 instance;return &instance;}
private:Singleton5() {}~Singleton5() {std::cout << "~Singleton5()\n";}Singleton5(const Singleton5 &) = delete;Singleton5& operator = (const Singleton5&) = delete;Singleton5(Singleton5 &&) = delete;Singleton5& operator = (Singleton5 &&) = delete;
};

静态局部变量具备单例的全部三个特性

最简单也是最推荐的版本


样例6

template<typename T>
class Singleton {
public:static T* GetInstance() {static T instance;return &instance;}
protected:Singleton() {}virtual ~Singleton() {std::cout << "~Singleton()\n";}
private:Singleton(const Singleton &) = delete;Singleton& operator = (const Singleton&) = delete;Singleton(Singleton &&) = delete;Singleton& operator = (Singleton &&) = delete;
};class DesignPattern : public Singleton<DesignPattern> {friend class Singleton<DesignPattern>;
private:DesignPattern() {}~DesignPattern() {std::cout << "~DesignPattern()\n";}
};

类模板封装单例的三个特性,使用时直接继承即可。

  • 基类构造和析构函数设置为protected是因为需要其对子类时可见的
  • 友元是为了让基类能访问子类的构造析构函数
http://www.dtcms.com/a/401500.html

相关文章:

  • 网站开发流程步骤 口袋广州百度推广优化排名
  • 扬州建设集团招聘信息网站商场设计开题报告
  • 网站建设选哪家成都网站设计制作
  • 网站软件应用大全淮北论坛招聘最新信息
  • 网站开发完要怎么部署crm客户管理系统
  • 网站膜拜销售石家庄自己的网站
  • 温州购物网络商城网站设计制作网络优化工具
  • 河北省建设厅网站工程师查询注册wordpress博客
  • 做网站应该注意些什么替换wordpress为QQ头像
  • 哈尔滨网站域名部门wordpress的编辑器插件
  • 郴州网站建设哪家公司好做教育导航的网站
  • 网站建设合同 附件粉红色主题 模板 网站 在线预览
  • 网站模板免费下载酒店管理系统深圳公司招聘网最新招聘信息
  • 如何制作百度网站地图wordpress用户前端页面
  • 怎么做网站关键词搜索成都有哪些网站开发公司
  • 哪个建站软件比较好带论坛免费商品展示页面设计模板
  • 做网站的条件摩托车网站建设
  • 怎么用txt做网站免费企业黄页网站入口
  • 佛山建设专业网站互联网软件外包平台
  • 医院网站建设方案详细点击运行显示网站正在建设
  • 网站开发申请报告微信公众号商城开发费用
  • 做医院网站公司吗微擎可以做企业网站吗
  • 百度站长平台链接提交网络营销方式优势
  • 如何做彩票网站信息html代码软件
  • 广东网站建设软件网站开发维护合同书
  • 做国外网站调查挣取零花钱湛江专业建站推广机构
  • Java SE
  • 怎么做网站软件滨州做网站多少钱
  • 网站开发兼职合同福田专业网站建设公司
  • 英文网站优化怎么制作免费的企业网站