博客
关于我
初夏小谈:设计模式之单例模式
阅读量:786 次
发布时间:2019-03-25

本文共 2093 字,大约阅读时间需要 6 分钟。

设计模式入门:探索单例模式与饿汉模式

设计模式是软件开发中反复使用的代码经验总结,它让代码更具可维护性和可扩展性。在本文中,我们探讨单例模式及其两种实现形式:饿汉模式和懒汉模式。

单例模式概述

单例模式是指在一个类中只能创建一个对象。这种设计思想确保了类独有的对象,使得资源管理更加高效,尤其在多线程环境下。单例模式通常提供了全局访问点,使得程序只需调用该点即可获得唯一的对象。

单例模式主要包含两种实现方式:饿汉模式和懒汉模式。这两种模式在设计单例对象时有不同的实现策略。以下将从饿汉模式开始深入探讨。


饿汉模式: 自始至终

饿汉模式的核心思想是“一旦启动程序,就立即创建对象”。无论是否需要这个对象,它都会在程序启动时就创建完成。这种方法节省了每次使用时因资源竞争带来的开销,尤其在频繁使用的多线程环境中非常高效。

饿汉模式的实现特点

  • 对象在程序启动时自发性地创建

    通过使用 static 关键字,确保对象在类加载时就被创建。

  • 防止类外构造对象

    通过私有化构造函数和拷贝构造函数,阻止类外直接创建对象。

  • 全局访问接口

    提供一个静态方法供外部获取该唯一对象,避免了对对象的直接访问操作。

  • 饿汉模式代码示例

    class Singleton {public:    static Singleton& GetSingleton() {        return Singleton::Object;    }private:    Singleton() {}    Singleton(const Singleton& s) {}    static Singleton Object;};Singleton Singleton::Object;

    饿汉模式的优点

    • 简化了资源管理:无需在其他地方管理对象生命周期。-避免资源竞争:在多线程环境下,直接获取全局对象,消除了竞争风险。

    懒汉模式: 懒得不能带

    懒汉模式则完全相反——在第一次需要使用对象时,程序才创建它。这种方式可以节省内存资源,尤其在对象频繁被使用的场景中。但由于其延迟初始化特性,也可能带来其他问题。

    懒汉模式的实现特点

  • 不在程序启动时创建对象

    通过检查对象状态,在需要时才进行创建。

  • 使用静态指针并加锁

    解决多线程环境中的竞态问题,确保对象只能由一个线程创建。

  • 延迟释放对象

    在程序退出时,确保最后一个使用该对象的线程完成后,及时释放内存。

  • 懒汉模式代码示例

    class Singleton {public:    static Singleton* GetObject() {        if (Singleton::object == nullptr) {            Mutex.lock();            if (Singleton::object == nullptr) {                Singleton::object = new Singleton();            }            Mutex.unlock();        }        return Singleton::object;    }    ~Singleton();    static Singleton* volatile object;    static Mutex Mutex;    static Clear clear;};Singleton* volatile Singleton::object = nullptr;Mutex Singleton::Mutex;Singleton::Clear Singleton::clear;

    懒汉模式的优点

    • 内存占用最优:只有在需要时才占用内存资源。
    • 线程安全:通过锁机制和双重检测,确保多线程环境下的安全性。
    • 延迟初始化:避免了不必要的对象创建开销。

    饮食模式(多线程下的懒汉模式)

    在单线程环境下,懒汉模式的实现较为简单。但在多线程环境中,可能会遇到如下问题:

  • 竞态问题

    如果在创建对象的同时,另一个线程试图调用该方法,可能会导致对象被创建多次。为此,需要使用锁机制。

  • 双检测问题

    临行时,由于编译器指令重排,可能导致在第一个对象创建时,其他线程仍然遇到未初始化对象的问题。为了解决,通常采用双重检测(先加锁,再检查一遍)。

  • 内存释放问题

    需要确保在最后一个线程调用完对象后,及时释放内存资源。

  • 解决方法

    为解决多线程环境下的懒汉模式问题,设计需要以下机制:

  • 加锁:确保只有一个线程可以执行对象创建逻辑。
  • 双检测:避免由于指令重排带来的潜在问题。
  • 延迟释放:在对象最后一次使用后,通过内部清理机制释放内存资源。
  • 关闭时自动清理:在程序退出时,确保所有动态内存被释放。

  • 通过上述分析,我们可以清晰地看到,选择-between-`饿汉模式和懒汉模式取决于具体应用场景和性能需求。在单线程环境中,饿汉模式可能更简单易于实现,而在多线程、高并发场景下,懒汉模式通过锁机制和双重检测,能够更好地处理资源竞争问题。

    转载地址:http://vncuk.baihongyu.com/

    你可能感兴趣的文章
    mysql 敲错命令 想取消怎么办?
    查看>>
    Mysql 整形列的字节与存储范围
    查看>>
    mysql 断电数据损坏,无法启动
    查看>>
    MySQL 日期时间类型的选择
    查看>>
    Mysql 时间操作(当天,昨天,7天,30天,半年,全年,季度)
    查看>>
    MySQL 是如何加锁的?
    查看>>
    MySQL 是怎样运行的 - InnoDB数据页结构
    查看>>
    mysql 更新子表_mysql 在update中实现子查询的方式
    查看>>
    MySQL 有什么优点?
    查看>>
    mysql 权限整理记录
    查看>>
    mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
    查看>>
    MYSQL 查看最大连接数和修改最大连接数
    查看>>
    MySQL 查看有哪些表
    查看>>
    mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
    查看>>
    MySql 查询以逗号分隔的字符串的方法(正则)
    查看>>
    MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
    查看>>
    mysql 查询数据库所有表的字段信息
    查看>>
    【Java基础】什么是面向对象?
    查看>>
    mysql 查询,正数降序排序,负数升序排序
    查看>>
    MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
    查看>>