单例模式,C/C++实现

单例模式作为最常见的设计模式之一,其重要性不言而喻,就我了解到的单例模式的应用场景:
1、在《Effective C++》中说到一种情况,有在两个不同的文件中定义的两个类,A和B。现在B需要用A来初始化,但是没办法保证A在B之前被初始化。这个时候可以设计成单例模式,在初始化B的时候调用A的getsingle()。
2、在设计线程池的时候,为了防止有多个线程池出现线程混乱通常把线程池设计成单例模式。
3、网络的访问计数一般也设计成单例模式,主要原因我想应该是为了实现同步。当然也可以设计成共享内存的方式,不过别忘了加锁。

讲了简单的应用场景以后,我们可以来简单了解下单例模式。
单例模式的实现主要有两种,就是所谓的饿汉和懒汉。

懒汉:
用时间来换空间,从他的名字我们可以理解,他很懒,不到用到绝对不实例化。
简单的懒汉:

class single
{
private:
    single(){}//将构造函数设为私有,不让其可以任意被实例化
    static single* p;
public:
    static signle* getsingle();
};
signle* signle::p=NULL;
single* single::getsingle()
{
    if(p==NULL)
        p=new single();
    return p;
}

这就是最简单的设计模式了,当然他存在很多问题。比如在多线程条件下如果同时遇到判断语句会出现什么情况呢?容易想到的解决办法是在判断语句前加锁,但是这又会出现一个问题,当线程数目很大的时候,会出现大量线程阻塞的情况。然后又有人想出了新的解决办法:

class single {
private:
    single()
    {
        pthread_mutex_init(&mutex);
    }
    static single* p;
public:
    static single* getsingle();
    pthread_mutex_t mutex;
};
single* single::p=NULL;
single* single::getsingle()
{
    if(p==NULL)
    {
        pthread_mutex_lock(&mutex);
        if(p==NULL)
            p=new single();
        pthread_mutex_unlock(&mutex);
    }
    return p;
}

可以看到,这种实现方式在加锁之前有加了一个判断语句,这在一定程度上减少了运行到加锁这一步的线程数目。

饿汉:
用空间来换时间,说实话,我感觉饿汉的实现方式看上去比懒汉的更加简单,而且也不用考虑线程安全。

class single
{
private:
    single(){}
    static single* p;
public:
    static single* getsingle();
};
single* single::p=new single();
single* single::getsingle()
{
    return p;
}

这种实现方式不用考虑线程安全的原因我想你应该看明白了,就是实例化的过程实现并不是在getsingle()中,在一开始就确定了只有一次实现。这种方式的缺点我想也比较明显,不管你是否用到,他从一开始就已经存在了。

说的不好的地方希望能指正,有补充的也欢迎。

你可能感兴趣的:(C++,设计模式)