单例饿汉式:
#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查询状态,如果不查询,子进程就是僵尸进程