Head First 设计模式——chapter5 单件模式C++实现

单件模式:

        有些类只应该存在一个实例。如线程池,缓存,注册表等对象。单件模式能确保一个类只有一个实例,并提供一个全局访问点。

        全局变量? 必须在程序刚开始就创建对象,而单件模式可以在需要时才创建对象。

实现:

        1.构造函数声明为私有。

        2.声明静态实例对象。

3.提供实例的全局访问点,当需要实例时,向类查询,它会返回静态实例对象。查询时可以采用延迟实例化的方式创建单件,这对于资源敏感的对象十分重要。

懒汉式:非线程安全。程序调用时才创建。

饿汉式:线程安全。程序编译时期创建类实例。

多线程操作出现问题:

1.同步getInstance  ()方法

需要加锁,但只有第一次执行此方法,才真正需要同步,之后的同步会引起程序效率下降。

2.先创建实例,不再延迟实例化。

当可能不需要实例对象时,提前静态初始化会占用一定的内存。

3.双重检查加锁

在getInstance()中不存在实例时才同步,解决1中同步引起效率下降的问题。

单件类析构:

不要直接使用类的析构函数来释放,否则将引起无休止的循环!

正确方法:另提供一个释放的接口,由这个单例的使用者来释放。

懒汉式 多线程不安全。

#include <iostream>
#include <mutex>
class Singleton
{
private:
    Singleton() {}
    static Singleton* uniqueInstance;
    
public:
    static Singleton* getInstance()
    {
        if (uniqueInstance == nullptr)
        {
            printf("uniqueInstance=nullptr\n");
            uniqueInstance = new Singleton();
        }
        printf("return uniqueInstance \n");
        return uniqueInstance;
    }
    ~Singleton(){}
    void destroy()
    {
        if (uniqueInstance != nullptr)
        {
            delete uniqueInstance;
            uniqueInstance = nullptr;
        }
    }

};
Singleton* Singleton::uniqueInstance = nullptr;

int main()
{
    Singleton* s1, * s2;
    
    thread thread1([&](){s1 = Singleton::getInstance(); });
    thread thread2([&]() { s2 = Singleton::getInstance(); });

    thread1.join();
    thread2.join();

    cout << (void*)s1 << endl;
    cout << (void*)s2 << endl;

    system("pause");
}

 地址不同。

安全的懒汉式(3,双重检查加锁):

#include <vector>
#include <unordered_map>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include<thread>
#include <mutex>
mutex m;
class Singleton
{
private:
	Singleton() {}
	static Singleton* uniqueInstance;

public:
	static Singleton* getInstance()
	{
	
		if (uniqueInstance == nullptr)
		{
			m.lock();
			if (uniqueInstance == nullptr)
			{
				printf("uniqueInstance=nullptr\n");
				uniqueInstance = new Singleton();
			}
			m.unlock();
		}
		printf("return uniqueInstance \n");
		return uniqueInstance;
	}
	~Singleton() {}
	void destroy()
	{
		if (uniqueInstance != nullptr)
		{
			delete uniqueInstance;
			uniqueInstance = nullptr;
		}
	}

};
Singleton* Singleton::uniqueInstance = nullptr;

int main()
{
	Singleton* s1, * s2;
	
	thread thread1([&](){s1 = Singleton::getInstance(); });
	thread thread2([&]() { s2 = Singleton::getInstance(); });

	thread1.join();
	thread2.join();

	cout << (void*)s1 << endl;
	cout << (void*)s2 << endl;

	system("pause");
}

 

饿汉式,线程安全

class Singleton
{
private:
	Singleton() {}
	static Singleton* uniqueInstance;
	
public:
	static Singleton* getInstance()
	{
		return uniqueInstance;
	}
	~Singleton(){}
	void destroy()
	{
		if (uniqueInstance != nullptr)
		{
			delete uniqueInstance;
			uniqueInstance = nullptr;
		}
	}

};
Singleton* Singleton::uniqueInstance = new Singleton();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值