设计模式

1. 单例设计模式

单例模式,是一种常用的软件设计模式。应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

具体实现

(1)将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。

(2)在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型。

(3)定义一个静态方法返回这个唯一对象。

实现一:饿汉式:该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了(所以,在外面的多线程访问这个接口时,对象只有一个,因此不存在多线程安全问题)。

class Single
{
    private:
             Single(){}
             static Single instance = new Single();
    public:
             static Single getInstance()
             {
                return instance;
             }
}

实现二:懒汉式:该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。

class Single
{
    private: 
            Singleton(){}
            static Single instance = null;
    public:
            static Single getInstance()
            {
                if(instance==null)
                {
                    instance = new Single();
                }
                return instance;
            }
}

单例类的获取是通过对外提供的:getInstance()接口,那么多个线程同时调用这个接口时可能会产生多个单例类,因此需要加锁。饿汉式在多线程下是安全的;懒汉式需要加锁,如下:

class Single
{
    private: 
            Singleton(){}
            static Single instance = null;
    public:
            std::mutex mutex;
            static Single getInstance()
            {
                std::lock_guard<std::mutex> lock(mutex); 
                if(instance==null)
                {
                    instance = new Single();
                }
                return instance;
            }
}

 

上面加锁的弊端时,使用一次(调用一次getInstance())就要加一次锁。。。真正应该是第一次创建类对象时加锁,如下:

下面的做法:不用让线程每次都加锁,而只是在实例未被创建时再加锁,这种做法称为:Double-Check Locking(双重锁定)

class Single
{
    private: 
            Singleton(){}
            static Single instance = null;
    public:
            std::mutex mutex;
            static Single getInstance()
            {
                if(instance==null)
                {
                    std::lock_guard<std::mutex> lock(mutex); 
                    if(instance==null)
                    {
                        instance = new Single();
                    }
                }
                return instance;
            }
}

第一个条件判断的意思是,某个线程实例化后,其他线程和此线程都不应该再进入了。
那么为什么里面还要再判断一次呢?
第二个条件判断的意思是,第一次实例化时,好几个线程一同进入加锁的位置,如果没有第二个条件,那么就不能避免重复创建类对象(线程1,2,3同时进入第一个if,得到null;然后线程1获得到了锁,线程2,3阻塞;线程1获得锁后,创建了单例对象,并释放了锁;然后线程2获取到了锁,此时线程2中的还为null;所以,如果不加里面的那层if判断,这时线程2又要创建对象了)。

还可以使用:std::call_once()来改造单例类(只被调用一次)

std::once_flag g_flag;

class Single
{
    private: 
            Singleton(){}
            static Single instance = null;
            static void creatInstance()
            {
                instance = new Single();
            }
    public:
            static Single getInstance()
            {
                if(instance==null)
                {
                    //假设两个线程多执行到了这里,其中一个线程要等另一个线程执行完毕 
                    std::call_once(g_flag, CreateInstance);
                }
                return instance;
            }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值