单例模式(Singleton)--遇到多线程时的问题

前面讲述了单例模式的基本概念:https://blog.csdn.net/Lunar_Queen/article/details/81774016。
然而,在多线程环境下,前面的程序段并不能保证真正的“单例”。
示例代码如下:

#include
#include
#include
using namespace std;

//单例模式

//构造函数私有化
//提供一个全局的静态变量方法
//在类中定义一个全局的指针


class Singleton
{
private:
    Singleton()//构造函数私有化
    {
        m_Count++;
        printf("Singleton Begin!!!\n");//使用printf()函数比较好
        Sleep(1000);
        printf("Singleton End!!!\n");
    }

public:
    static Singleton* GetSingelton()//提供一个全局的访问点
    {
        /*
        //此写法不能保证单例,必须加上判断
        return new Singleton();
        */

        if(single==NULL)
        {//每一次都需要判断该单例是否存在?

            single=new Singleton();//有可能导致多个线程调用词语局,导致非单例
        }

        return single;
    }

    static void Print()
    {
        printf("Calling Count=%d\n",m_Count);
    }

private:
    static Singleton* single;

    static int        m_Count;//增加一个计数器,标识构造函数被调用的次数
};

Singleton*  Singleton::single=NULL;//在类外对类中的数据成员进行初始化
int         Singleton::m_Count=0;
/*
int main()
{
    //目的:不希望客户调用构造函数;不希望客户构造两个同类型的对象,防止资源浪费。
    //Singleton* p1=new Singleton;//出错,构造函数已经私有化。
    //Singleton* p2=new Singleton;

    Singleton* p1=Singleton::GetSingelton();
    Singleton* p2=Singleton::GetSingelton();

    if(p1==p2)
    {
        cout<<"p1==p2"<
//分析
 //此模式为典型的懒汉模式,因为呐。只有在GetSingelton()这个函数被调用时,
 //才会new一个单例。

//缺点:new时才会调用构造函数,C++的构造函数不是线程安全的。

//线程安全性演示
//懒汉式--遇到多线程问题--原因呢?判断语句根本不起作用。


void MyThreadFunc (void *p)
{
    printf("ThreadID=%d\n",GetCurrentThreadId());

    Singleton *single=Singleton::GetSingelton();
    Singleton::Print();
    return;
}

int main()
{
    int ThreadNum=3;

    HANDLE HThread[3];

    for(int i=0;i0,NULL);//返回线程句柄,可以操作线程--挂起、暂停
    }

    for(int i=0;i//让主线程等待所有的子线程运行完毕,或者说让操作系统挂起主线程。
        WaitForSingleObject(HThread[i],INFINITE );
    }

    printf("main() endling\n");
    return 0;
}

//分析--一次调用两次返回。
//主进程消失,子进程不一定消失。孤儿进程。
//主线程消失,子线程也消失。

执行上述程序,运行结果如下图所示:
单例模式(Singleton)--遇到多线程时的问题_第1张图片
可以看到,单例模式下产生的实例并非“单例”。

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