单例模式 定义:是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。
实现单例的步骤: 1.构造函数私有化 2.提供一个全局的静态方法(全局访问点) 3.在类中定义一个静态指针,指向本类的变量的静态变量指针。
#include <iostream> using namespace std; class singleton { private: singleton() { ; } public: static singleton * Getsingleton() { //在每一次Getsingleton的时候,都需要判断sigle是否存在 if (sigle == NULL) { sigle = new singleton; } return sigle; } public: static singleton * sigle; }; //静态变量的初始化 singleton * singleton::sigle = NULL; int main() { //只有我们调用的Getsingleton时候,类才会new出对象。==》懒汉式 //优点:节省空间 //缺点:C++构造函数不能保证线程安全 singleton * s1 = singleton::Getsingleton(); singleton * s2 = singleton::Getsingleton(); if (s1 == s2) { printf("s1 == s2\n "); } else { cout << "s1 != s2" << endl; } system("pause"); }但是懒汉式又存在着线程安全的隐患。即多个进程竞争,恰好在“恰当”的位置失去CPU的时间轮片。就会出现不是单例的情况。示例代码如下:
“饿汉式”:
#include <iostream> using namespace std; #include <process.h> #include <WinBase.h> #include <Windows.h> class singleton { private: static singleton * sigle; static int m_count; private: //C++构造函数不能保证线程安全 singleton() { m_count++; printf("singleton begin!\n"); Sleep(1000); printf("singleton end!\n"); } public: static singleton * Getsingleton() { //在每一次Getsingleton的时候,都需要判断sigle时候存在 if (sigle == NULL) { sigle = new singleton; } return sigle; } static void printS() { printf("m_count:%d\n", m_count); } }; //静态变量的初始化 singleton * singleton::sigle = NULL; int singleton::m_count = 0; void thread_func(void * arg) { DWORD id = GetCurrentThreadId(); printf("%dst thread!\n", id); singleton::Getsingleton()->printS() } int main() { int threadnum = 3; HANDLE threadfd[100]; int i = 0; for (i = 0; i < threadnum; i++) { threadfd[i] = (HANDLE)_beginthread(thread_func, 0, NULL); if (threadfd[i] == NULL) { printf("_beginthread[%d] error\n", i); break; } } //主线程阻塞 for (i = 0; i < threadnum; i++) { WaitForSingleObject(threadfd[i], INFINITE); } printf("main"); system("pause"); }在windows环境下,多线程API是真的不好记呀。还是在Linux下比较简便。
那如何解决这个安全隐患呢? “饿汉式”:
#include <iostream> using namespace std; #include <process.h> #include <WinBase.h> #include <Windows.h> class singleton { private: static singleton * sigle; static int m_count; private: //C++构造函数不能保证线程安全 singleton() { m_count++; printf("singleton begin!\n"); Sleep(1000); printf("singleton end!\n"); } public: static singleton * Getsingleton() { return sigle; } static void printS() { printf("m_count:%d\n", m_count); } }; //静态变量的初始化 //饿汉式 //优点:线程安全 //缺点:提前创建,浪费内存 singleton * singleton::sigle = new singleton; int singleton::m_count = 0; void thread_func(void * arg) { DWORD id = GetCurrentThreadId(); printf("%dst thread!\n", id); singleton::Getsingleton()->printS(); } //1.主线程退出,子进程也退出 //2. int main() { //_ACRTIMP uintptr_t __cdecl _beginthread(_In_beginthread_proc_type _StartAddress, // _In_ unsigned _StackSize, _In_opt_ void* _ArgList); int threadnum = 3; HANDLE threadfd[100]; int i = 0; for (i = 0; i < threadnum; i++) { threadfd[i] = (HANDLE)_beginthread(thread_func, 0, NULL); if (threadfd[i] == NULL) { printf("_beginthread[%d] error\n", i); break; } } //主线程阻塞 for (i = 0; i < threadnum; i++) { WaitForSingleObject(threadfd[i], INFINITE); } printf("main"); system("pause"); }线程竞争的“锁”机制
#include <iostream> using namespace std; #include <process.h> #include <WinBase.h> #include <Windows.h> //临界区 static CCriticalSection cs; class singleton { private: static singleton * sigle; static int m_count; private: //C++构造函数不能保证线程安全 singleton() { m_count++; printf("singleton begin!\n"); Sleep(1000); printf("singleton end!\n"); } public: static singleton * Getsingleton() { //在每一次Getsingleton的时候,都需要判断sigle时候存在 if (sigle == NULL) { cs.Lock(); //只有当sigle等于NULL时,才开始使用加锁机制 二次检查 if (sigle == NULL) { sigle = new singleton; } cs.Unlock(); } return sigle; } static void printS() { printf("m_count:%d\n", m_count); } }; //静态变量的初始化 singleton * singleton::sigle = NULL; int singleton::m_count = 0; void thread_func(void * arg) { DWORD id = GetCurrentThreadId(); printf("%dst thread!\n", id); singleton::Getsingleton()->printS(); } int main() { int threadnum = 3; HANDLE threadfd[100]; int i = 0; for (i = 0; i < threadnum; i++) { threadfd[i] = (HANDLE)_beginthread(thread_func, 0, NULL); if (threadfd[i] == NULL) { printf("_beginthread[%d] error\n", i); break; } } //主线程阻塞 for (i = 0; i < threadnum; i++) { WaitForSingleObject(threadfd[i], INFINITE); } printf("main"); system("pause"); }最近在学习设计模式,暂时先总结,后面有感悟再来补充和修改。