单例模式
单例模式有两种,懒汉和饿汉
懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化。与之对应的是饿汉式单例。(注意,懒汉本身是线程不安全的)
饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。(本身就是线程安全的)
1 线程安全、内存安全的懒汉式单例 (智能指针,锁)
#include <iostream>
#include <memory> // shared_ptr
#include <mutex> // mutex
// version 2:
// with problems below fixed:
// 1. thread is safe now
// 2. memory doesn't leak
class Singleton {
public:
typedef std::shared_ptr<Singleton> Ptr;
~Singleton() {
std::cout << "destructor called!" << std::endl;
}
Singleton(Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Ptr get_instance() {
// "double checked lock"
if (m_instance_ptr == nullptr) {
std::lock_guard<std::mutex> lk(m_mutex);
if (m_instance_ptr == nullptr) {
m_instance_ptr = std::shared_ptr<Singleton>(new Singleton);
}
}
return m_instance_ptr;
}
private:
Singleton() {
std::cout << "constructor called!" << std::endl;
}
static Ptr m_instance_ptr;
static std::mutex m_mutex;
};
// initialization static variables out of class
Singleton::Ptr Singleton::m_instance_ptr = nullptr;
std::mutex Singleton::m_mutex;
int main() {
Singleton::Ptr instance = Singleton::get_instance();
Singleton::Ptr instance2 = Singleton::get_instance();
return 0;
}
2 饿汉式的单例实现
#include <iostream>
#include <process.h>
#include <windows.h>
using namespace std;
class Singelton{
private:
Singelton(){
m_count ++;
printf("Singelton begin\n");
Sleep(1000); // 加sleep为了放大效果
printf("Singelton end\n");
}
static Singelton *single;
public:
static Singelton *GetSingelton();
static void print();
static int m_count;
};
// 饿汉模式的关键:初始化即实例化
Singelton *Singelton::single = new Singelton;
int Singelton::m_count = 0;
Singelton *Singelton::GetSingelton(){
// 不再需要进行实例化
//if(single == nullptr){
// single = new Singelton;
//}
return single;
}
void Singelton::print(){
cout<<m_count<<endl;
}
// 回调函数
void threadFunc(void *p){
DWORD id = GetCurrentThreadId(); // 获得线程id
cout<<id<<endl;
Singelton::GetSingelton()->print(); // 构造函数并获得实例,调用静态成员函数
}
int main(int argc, const char * argv[]) {
int threadNum = 3;
HANDLE threadHdl[100];
// 创建3个线程
for(int i = 0; i<threadNum; i++){
threadHdl[i] = (HANDLE)_beginthread(threadFunc, 0, nullptr);
}
// 让主进程等待所有的线程结束后再退出
for(int i = 0; i<threadNum; i++){
WaitForSingleObject(threadHdl[i], INFINITE);
}
cout<<"main"<<endl; // 验证主进程是否是最后退出
return 0;
}