• 设计模式:单例模式(singleton)


    singleton模式属于创建型设计模式。其作用是在程序设计中,对于某一个类而言,全局只能存在一个实例对象。

    下面以C++为例,对单例模式进行说明:

    1. 最基本单例模式(单线程) 

     1 class Singleton1{
     2     private:
     3         static Singleton1 instance;
     4         Singleton1(){}            //构造函数
     5     public:
     6         static Singleton1 get_instance(){
     7             if (Singleton1.instance==nullptr){   //若当前唯一实例为空,则创建新对象返回
     8                 instance=Singleton1();
     9             }
    10             return instance;
    11         } 
    12 };

    存在问题:在单线程下,只有instance == null 时,才会创建新对象,其余时间返回。但是对于多线程访问时,当两个或多个线程同时访问到instance==null,若判断成立,多个线程会分别实例化对象,这时程序就不满足单例条件了。

    2.多线程的单例模式

    针对上述问题,要在多线程中保证单例,就要进行线程同步控制,C++中使用mutex类族进行同步控制。

    class Singleton2{
        private:
            static Singleton2 instance;
            static std::mutex mutex_var; 
            Singleton2(){}
        public:
            static Singleton2 get_instance(){
                mutex_var.lock();           //互斥量加锁进行线程同步
                if (instance==nullptr){
                    instance=Singleton2();
                }
                mutex_var.unlock();         //互斥量解锁
                return instance;
            } 
    };

    存在问题:线程安全,但程序效率不高。注意,此前讨论的出现的不满足单例的情况只出现在首次实例化对象时,但现在的程序在每次通过ger_instance函数访问时,都会进行加解锁操作,,加锁操作是十分耗时的,从而导致程序效率变低。

    3.多线程下高效的单例模式

    解决方法:仅在第一次实例化的时候加锁,其他时刻不加锁,提高程序效率。

    class Singleton3{
        private:
            static Singleton3 instance;
            static std::mutex mutex_var; 
            Singleton3(){}
        public:
            static Singleton3 get_instance(){
                if (instance==nullptr)         //外层多一次判断,如果单例已经存在,就不再进行加锁操作
                {
                    mutex_var.lock();           //互斥量加锁进行线程同步
                    if (instance==nullptr){
                        instance=Singleton3();
                    }
                    mutex_var.unlock();         //互斥量解锁
                }
                return instance;
            } 
    };

    关于懒汉式和饿汉式的讨论

    饿汉式:单例实例在类装载时就构建,急切初始化。(预先加载法)

    懒汉式:单例实例在第一次被使用时构建,延迟初始化。(上述实现都是懒汉式的)。

    这两类单例模式的区别在于实例化的时机不同。

    饿汉式

    优点:线程安全,在类加载的同时创建一个静态对象,调用时反应快。缺点:由于是提前定义,可能在全局程序中都没有使用这个实例,资源利用率不高。

    懒汉式 

    优点:资源效率高,只要不用到该实例就不会被实例化。缺点:第一次加载速度不快。

    两种方式各有优劣,针对不同的场景进行选择,一般情况下,使用饿汉式更多一些。

  • 相关阅读:
    企信通自动登录问题解决
    BPM保存提交审核时后台校验数据
    初始化BPM
    BPM删除事件,删除表单
    flowportal数据字典
    百度网盘
    HPC 有哪些应用层?
    公众号改名字了:子郁定投上海
    一些网站和他们的关键词介绍
    如何找到女朋友
  • 原文地址:https://www.cnblogs.com/fancy-li/p/11606914.html
Copyright © 2020-2023  润新知