C++学习经历(十)设计模式——单例模式

什么是单例模式

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例

其中单例模式的具体实现如下:

饿汉形式——当类被加载的时候便进行初始化单例对象

直接在加载后初始化

#include <iostream>
#include <pthread.h>


using namespace std;


pthread_mutex_t mutex;
class Singleton
{
    private:
        static Singleton *mInstance;
        static int handlecount;
    private:
        Singleton()
        {


        }
    public:
        static Singleton *GetInstance()
        {
            /*
            if(NULL == mInstance)
            {
                usleep(100000);
                mInstance = new Singleton;
            }
            */
            handlecount ++;
            return mInstance;
        }
        static int Gethandlecount()
        {
            return handlecount;
        }


        void release()
        {
            handlecount --;
            if(handlecount == 0 && mInstance != NULL)
            {
                delete mInstance;
                cout << "释放成功" << endl;
            }
        }
};


Singleton *Singleton::mInstance = new Singleton;
int Singleton::handlecount = 0;


void *createl(void *arg)
{   
    //pthread_mutex_lock(&mutex);
    Singleton *s1 = Singleton::GetInstance();
    cout << s1 << endl;
    //pthread_mutex_unlock(&mutex);
}


int main(int argc, char **argv)
{/*
    Singleton *s1 = Singleton::GetInstance();
    Singleton *s2 = Singleton::GetInstance();
    Singleton *s3 = Singleton::GetInstance();
    Singleton *s4 = Singleton::GetInstance();
    
    cout << s1 << endl;
    cout << s2 << endl;
    cout << s3 << endl;
    cout << s4 << endl;


    if(s1 == s2)
    {
        cout << "对象相同"  << endl;
    }
    else
    {
        cout << Singleton::Gethandlecount() << endl;
    }
    cout << Singleton::Gethandlecount() << endl;
    
    s1 -> release(); 
    s2 -> release();
    s3 -> release();
    s4 -> release();
    cout << Singleton::Gethandlecount() << endl;
*/
    pthread_t pthread_id[20];
    void *val;


    //pthread_mutex_init(&mutex,NULL);


    for(int i = 0;i < 20;i++)
    {
        pthread_create(&pthread_id[i],NULL,createl,NULL);
    }


    for(int i = 0;i < 20;i++)
    {
        pthread_join(pthread_id[i],&val);
    }


    //pthread_mutex_destroy(&mutex);


    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9


懒汉形式——当需要使用单例对象时进行初始化操作(多版本)

版本1:

public class SingleDemo{

    private static SingleDemo demo = null;
    private SingleDemo(){}

    public static SingleDemo getDemo(){
        if(demo == null){
            demo = new SingleDemo();
        }
        return demo;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这是最简单的版本,但是有个致命的问题就是,它不是一个线程安全的例子,也就是说在多线程环境下,并不总能保证单例。

版本2:

public class SingleDemo{

    private static SingleDemo demo = null;

    private SingleDemo(){}

    public synchronized static SingleDemo getDemo(){
        if(demo == null){
            demo = new SingleDemo();
        }
        return demo;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

通过对方法上锁,实现的线程安全的获取单例的操作,但是很遗憾,因为这个方法在绝大多数情况下是不需要同步的,加锁严重降低了程序执行的效率,所以不提倡使用。

版本3:

public class SingleDemo{

    private static SingleDemo demo = null;

    private SingleDemo(){}

    public  static SingleDemo getDemo(){
        if(demo == null){
            synchronized(SingleDemo.class) {
                demo = new SingleDemo();
            }
        }
        return demo;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

对版本2进行优化后,可以明显提高程序的效率,但是很遗憾,这段代码并不能保证线程安全。

版本4:

public class SingleDemo{

    private static SingleDemo demo = null;

    private SingleDemo(){}

    public  static SingleDemo getDemo(){
        if(demo == null){
            synchronized(SingleDemo.class) {
                if(demo == null) {
                    demo = new SingleDemo();
                }
            }
        }
        return demo;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这是上述版本的最终形态,俗称双检锁模式,通过双重校验,达到了线程安全的目的,同时避免了代码频繁上锁解锁的过程。

版本5:

public class SingleDemo{

    private SingleDemo(){}

    private static class Singleton{
        private static final SingleDemo DEMO = new SingleDemo();
    }

    public  static SingleDemo getDemo(){
        return Singleton.DEMO;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这样至少看起来代码简洁不少,不仅达到了懒加载的效果,还实现了线程安全。

版本6:

public enum SingleDemo{
    DEMO;
    public  static SingleDemo getDemo(){
        return DEMO;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

最后这种是通过枚举实现的单例,但是现实用到的不多,该模式为Effective Java作者Josh Bloch 所推崇,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象(如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例)。

#include <iostream>
#include <pthread.h>

using namespace std;

pthread_mutex_t mutex;
class Singleton
{
    private:
        static Singleton *mInstance;
        static int handlecount;
    private:
        Singleton()
        {

        }
    public:
        static Singleton *GetInstance()
        {
            if(NULL == mInstance)
            {
                usleep(100000);
                mInstance = new Singleton;
            }
            handlecount ++;
            return mInstance;
        }
        static int Gethandlecount()
        {
            return handlecount;
        }

        void release()
        {
            handlecount --;
            if(handlecount == 0 && mInstance != NULL)
            {
                delete mInstance;
                cout << "释放成功" << endl;
            }
        }
};

Singleton *Singleton::mInstance = NULL;
int Singleton::handlecount = 0;

void *createl(void *arg)
{   
    pthread_mutex_lock(&mutex);
    Singleton *s1 = Singleton::GetInstance();
    cout << s1 << endl;
    pthread_mutex_unlock(&mutex);
}

int main(int argc, char **argv)
{/*
    Singleton *s1 = Singleton::GetInstance();
    Singleton *s2 = Singleton::GetInstance();
    Singleton *s3 = Singleton::GetInstance();
    Singleton *s4 = Singleton::GetInstance();
    
    cout << s1 << endl;
    cout << s2 << endl;
    cout << s3 << endl;
    cout << s4 << endl;

    if(s1 == s2)
    {
        cout << "对象相同"  << endl;
    }
    else
    {
        cout << Singleton::Gethandlecount() << endl;
    }
    cout << Singleton::Gethandlecount() << endl;
    
    s1 -> release(); 
    s2 -> release();
    s3 -> release();
    s4 -> release();
    cout << Singleton::Gethandlecount() << endl;
*/
    pthread_t pthread_id[20];
    void *val;

    pthread_mutex_init(&mutex,NULL);

    for(int i = 0;i < 20;i++)
    {
        pthread_create(&pthread_id[i],NULL,createl,NULL);
    }

    for(int i = 0;i < 20;i++)
    {
        pthread_join(pthread_id[i],&val);
    }

    pthread_mutex_destroy(&mutex);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhanganliu/article/details/80328727