设计模式--单例


单例饿汉式:

#include<iostream>
#include<Windows.h>
#include<process.h>
#include<WinBase.h>
using namespace std;
//1 懒汉式
	//1 构造函数私有化
	//2 提供静态成员函数做全局接口
	//3 定义静态指针
	//4 在接口中判断是否new
//优缺点:
	//构造函数不是线程安全的,多线程时,若new的时候延时过多,可能会创建出多个实例
//解决办法:
	//1 饿汉式
	//2 临界区doublecheck
		//第一次判断是否有实例
		//第二次加锁后判断实例是否被new出

//2 饿汉式 static Singelton* single初始值就new出来对象
	//缺点:程序运行就存在,可能会浪费资源

//3 改进懒汉式 
	//实质是多线程竞争一个资源,加把锁就可以

class Singelton
{
private: //1 构造函数私有化
		 //C++的构造函数不能保证线程安全
	Singelton()
	{
		++m_num;
		printf("Singelton begin\n");
		Sleep(1000);
		printf("Singelton end\n");
	}
public:
	static void printS()
	{
		printf("m_num : %d\n", m_num);
	}
public://2 提供全局访问点
	static Singelton * GetSingelton()
	{
		//if (single == NULL) //每一次GetSingelton时,都判断实例是否存在
		//{
		//	single = new Singelton;//线程1 2 3 都去调用了new Singelton 原因:new中延时太长,还没new出来实例,下一个线程就来了
		//}
		return single;

	}

private://3 指针
	static Singelton *single;
	static int m_num;
};
Singelton * Singelton::single = new Singelton; //饿汉式,在初始化时就new出来
int Singelton::m_num = 0;

void main01()
{
	Singelton *s1 = Singelton::GetSingelton();
	Singelton *s2 = Singelton::GetSingelton();
	if (s1 == s2)
	{
		cout << "s1 == s2" << endl;
	}
	else
	{
		cout << "s1 != s2" << endl;
	}

	system("pause");
}
void threadFun(void *p)
{
	DWORD id = GetCurrentThreadId();
	Singelton::GetSingelton()->printS();
	printf("id:%d\n", id);
	return;
}

void main()
{
	int threadnum = 3;
	HANDLE threadhdl[100];
	for (int i = 0; i < threadnum; ++i)
	{
		//_beginthread()函数定义:
		//	_ACRTIMP uintptr_t __cdecl _beginthread(
		//		_In_     _beginthread_proc_type _StartAddress,
		//	_In_     unsigned               _StackSize,
		//_In_opt_ void*                  _ArgList);
		//typedef void     (__cdecl*   _beginthread_proc_type  )(void*);
		threadhdl[i] = (HANDLE)_beginthread(threadFun, 0, NULL); //创建线程
	}
	for (int i = 0; i < threadnum; ++i)
	{
		//让父进程等待所有的子线程运行完毕
		//子线程返回后,通知main函数事件对象
		WaitForSingleObject(threadhdl[i], INFINITE);
	}
	printf("main\n");
	system("pause");
}

//1 主进程消失,在主进程中创建的线程也消失,线程的内存四区依赖于进程的内存四区。
//2 主进程创建了子进程,每个进程有自己独立的运行空间,主进程消失,子进程不消失。让子进程不提前死,让主进程等一等。
//3 托孤:让0号进程收管孤儿进程,子进程结束后还有资源描述符,父进程用wait和waitpid查询状态,如果不查询,子进程就是僵尸进程

单例懒汉式:

#include<iostream>
#include<Windows.h>
#include<process.h>
#include<WinBase.h>
using namespace std;
//1 懒汉式
//2 饿汉式 static Singelton* single初始值就new出来对象
class Singelton
{
private: //1 构造函数私有化
	//C++的构造函数不能保证线程安全
	Singelton()
	{
		++m_num;
		printf("Singelton begin\n");
		Sleep(1000);
		printf("Singelton end\n");
	}
public:
	static void printS()
	{
		printf("m_num : %d\n", m_num);
	}
public://2 提供全局访问点
	static Singelton * GetSingelton()
	{
		if (single == NULL) //每一次GetSingelton时,都判断实例是否存在
		{
			single = new Singelton;//线程1 2 3 都去调用了new Singelton 原因:new中延时太长,还没new出来实例,下一个线程就来了
		}
		return single;
		
	}
	
private://3 指针
	static Singelton *single;
	static int m_num;
};
Singelton * Singelton::single = NULL;
int Singelton::m_num = 0;

//1 简单测试
void main011()
{
	//只有当我们调用GetSingelton时,类才会new出对象(在new对象的时候做判断)==>比较懒 懒汉式
	//优点
	//缺点
	Singelton *s1 = Singelton::GetSingelton();
	Singelton *s2 = Singelton::GetSingelton();
	if (s1 == s2)
	{
		cout << "s1 == s2" << endl;
	}
	else
	{
		cout << "s1 != s2" << endl;
	}

	system("pause");
}
void threadFun(void *p)
{
	DWORD id = GetCurrentThreadId();
	Singelton::GetSingelton()->printS();
	printf("id:%d\n", id);
	return;
}

//2 多线程引起问题演示
//new延时过长,多线程会创建多个单例
void main012()
{
	int threadnum = 3;
	HANDLE threadhdl[100];
	for (int i = 0; i < threadnum; ++i)
	{
	//	_ACRTIMP uintptr_t __cdecl _beginthread(
	//		_In_     _beginthread_proc_type _StartAddress,
		//	_In_     unsigned               _StackSize,
		//_In_opt_ void*                  _ArgList);
		//typedef void     (__cdecl*   _beginthread_proc_type  )(void*);
		threadhdl[i] = (HANDLE)_beginthread(threadFun, 0, NULL);
	}
	for (int i = 0; i < threadnum; ++i)
	{
		//让父进程等待所有的子线程运行完毕
		WaitForSingleObject(threadhdl[i], INFINITE);
	}
	printf("main\n");
	system("pause");
}

//1 主进程消失,在主进程中创建的线程也消失,线程的内存四区依赖于进程的内存四区。
//2 主进程创建了子进程,每个进程有自己独立的运行空间,主进程消失,子进程不消失。让子进程不提前死,有函数让主进程等一等。
//3 托孤:让0号进程收管孤儿进程,子进程结束后还有资源描述符,父进程用wait和waitpid查询状态,如果不查询,子进程就是僵尸进程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值