当前位置:网站首页>线程安全的单例模式
线程安全的单例模式
2022-07-03 02:11:00 【abs(ln(1+NaN))】
所谓单例,就是某些类,只能有一个对象
当一个对象被创建出来的时候,首先需要为这个对象开辟空间,然后再调用构造函数来初始化这个对象。然而在单例模式下,这个过程只能出现一次,为了达到这个目的,我们需要满足以下两个条件:
(1) 让内存中仅存在一个对象,这个对象需要类的内部创建,同时使用static修饰(static修饰的变量会放在全局区)
(2) 为了不让类外出现该类的其他对象,我们要将各种构造函数放在private里(如果默认构造、有参构造、拷贝构造用不到,可以使用delete禁用)
目录
一、单例模式的两种情况
在上述的基础上,既然是创建对象,应该什么时候创建呢??这里就分为了两种情况,一种是饿汉方式,一种是懒汉方式。
- 饿汉方式:立马把碗洗干净,方便后面干饭。程序开始运行的时候就把对象创建好
- 懒汉方式:悠哉游哉,等需要时再干饭。等需要用到对象的时候,再主动创建
二、懒汉方式的单例模式
下面以某个单例类为例,这个类使用单例模式中的懒汉方式,也就是等到要使用对象的时候再创建对象,下面就按照上面的两个条件来依次实现。
1、在类内创建对象(要求一)
首先是创建唯一的对象,并用static修饰。唯一的对象在类内部,在类外必然就无法通过下面两种方式来获取
Sington sig; // 错误
Sington* sig = new Sington(); // 错误外部要使用这个对象,肯定是通过类来直接或者间接获取的,既然要通过类来获取,那就需要加上static来修饰

static修饰的成员函数要在类外初始化,初始化的方式类似于类成员函数在类外初始化
变量类型 类名::变量名 = 变量值
2、构造函数私有化或禁用构造函数(要求二)
上面这步只是创建了我们想要的唯一的对象,那么要如何禁止外界创建对象呢??
答案是:将构造函数放在 private 中,或者禁用一部分的构造函数
==》对象在类内被创建的时候,可以调用private里的构造函数;但是如果对象在类外被创建时,public中找不到对应的构造函数,此时就会报错

为什么禁用:假设我们使用获取到的唯一的对象sig 来创建其他对象,内存中Sington类就会有不止一个对象了,这就违背了单例的原则,所以我们要禁用拷贝构造函数
Sington sig1(sig); //拷贝构造函数3、给外部提供获取对象的接口
由于创建出来的对象是放在private中的,类外无法直接访问,所以我们需要给提供一个类外访问的接口,最初版本如下:

但是当有多个线程同时访问这个接口的时候,这个时候存在线程安全问题,我们要保护sig这个临界资源,所以要给临界资源加锁,使用的锁也必须是static修饰的

![]()

现在当一个线程好不容易申请到锁了,但是进去一看,发现 sig 已经被其他线程初始化了,申请锁就显得多此一举,所以我们最好在申请锁之前,再加一道判断,先判断是不是空的,再申请锁。

三、单例模式测试
我们在主线程里创建 5 个线程,每隔1s打印一次当前获取到的对象的地址,以及线程ID

测试结果如下:

四、拓展:饿汉模式(简单介绍)
饿汉模式就是在程序开始运行的时候创建,不同之处在于对象声明方式。
不带*号代表在栈上开辟,这个时候对象在被创建的时候就会被分配空间

在接口函数里,就无需判断是否为空了,直接返回即可

返回值加&的原因是 防止隐式调用拷贝构造函数
边栏推荐
- Leetcode 183 Customers who never order (2022.07.02)
- Machine learning notes (constantly updating...)
- 微服务组件Sentinel (Hystrix)详细分析
- [shutter] hero animation (hero realizes radial animation | hero component createrecttween setting)
- 8 free, HD, copyright free video material download websites are recommended
- Leetcode(540)——有序数组中的单一元素
- Where is the future of test engineers? Confused to see
- MySQL learning 03
- SPI机制
- 浏览器是如何对页面进行渲染的呢?
猜你喜欢
![[shutter] hero animation (hero realizes radial animation | hero component createrecttween setting)](/img/e7/915404743d6639ac359bb4e7f7fbb7.jpg)
[shutter] hero animation (hero realizes radial animation | hero component createrecttween setting)

stm32F407-------IIC通讯协议

RestCloud ETL 跨库数据聚合运算

In 2022, 95% of the three most common misunderstandings in software testing were recruited. Are you that 5%?

udp接收队列以及多次初始化的测试

Ni visa fails after LabVIEW installs the third-party visa software

MySQL learning 03

Asian Games countdown! AI target detection helps host the Asian Games!

Huakaiyun (Zhiyin) | virtual host: what is a virtual host

Job object of collaboration in kotlin
随机推荐
502 (bad gateway) causes and Solutions
Iptables layer 4 forwarding
详细些介绍如何通过MQTT协议和华为云物联网进行通信
4. 类和对象
easyExcel
树形结构数据的处理
Query product cases - page rendering data
Detailed introduction to the deployment and usage of the Nacos registry
DDL basic operation
[camera topic] how to save OTP data in user-defined nodes
Cfdiv2 fixed point guessing- (interval answer two points)
[Yu Yue education] China Ocean University job search OMG reference
微信小程序开发工具 POST net::ERR_PROXY_CONNECTION_FAILED 代理问题
SPI机制
DML Foundation
Analyzing several common string library functions in C language
转载收录6.5大侠写的部分Qt开发经验
A 30-year-old software tester, who has been unemployed for 4 months, is confused and doesn't know what to do?
The Sandbox阐释对元宇宙平台的愿景
Su Shimin: 25 principles of work and life