单例模式(Singleton)--多线程问题解决办法

前面提到单例模式在多线程环境下并非“单例”:https://blog.csdn.net/Lunar_Queen/article/details/81776647
下面提出了一种解决该问题的方法:类的静态数据成员只会被初始化一次。
示例代码如下:

#include<iostream>
#include<Windows.h>
#include<process.h>
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=new Singleton();//在类外对类中的数据成员进行初始化
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"<<endl;
    }
    else
    {
        cout<<"p1!=p2"<<endl;
    }

    return 0;
}
*/
//分析
 //此模式为典型的懒汉模式,因为呐。只有在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;i<ThreadNum;++i)
    {
         HThread[i]=(HANDLE)_beginthread(MyThreadFunc,0,NULL);//返回线程句柄,可以操作线程--挂起、暂停
    }

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

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

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


//饿汉式单例模式--可保证构造函数仅被调用一次。
//在静态成员指针变量初始化时给其赋予初值。

执行上述程序,运行结果如下图所示:
这里写图片描述
可以看到,仅产生了类的一个实例。

猜你喜欢

转载自blog.csdn.net/Lunar_Queen/article/details/81776846