当前位置:网站首页>线程安全的单例模式
线程安全的单例模式
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

测试结果如下:

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

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

返回值加&的原因是 防止隐式调用拷贝构造函数
边栏推荐
- Rockchip3399 start auto load driver
- 疫情当头,作为Leader如何进行团队的管理?| 社区征文
- CFdiv2-Fixed Point Guessing-(區間答案二分)
- Leetcode 183 Customers who never order (2022.07.02)
- 技术大佬准备就绪,话题C位由你决定
- Detailed introduction to the deployment and usage of the Nacos registry
- 返回一个树形结构数据
- 单词单词单词
- 疫情當頭,作為Leader如何進行團隊的管理?| 社區征文
- 创建+注册 子应用_定义路由,全局路由与子路由
猜你喜欢

Servlet中数据传到JSP页面使用el表达式${}无法显示问题

详细些介绍如何通过MQTT协议和华为云物联网进行通信

stm32F407-------ADC

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

【Camera专题】手把手撸一份驱动 到 点亮Camera

Job object of collaboration in kotlin

MySQL learning 03

通达OA v12流程中心

Depth (penetration) selector:: v-deep/deep/ and > > >

Button button adaptive size of wechat applet
随机推荐
Machine learning notes (constantly updating...)
Visual yolov5 format data set (labelme JSON file)
[Flutter] dart: class;abstract class;factory;类、抽象类、工厂构造函数
Cfdiv2 fixed point guessing- (interval answer two points)
What are the key points often asked in the redis interview
easyExcel
COM和CN
Network security OpenVAS
Socket编程
MySQL learning 03
Learn BeanShell before you dare to say you know JMeter
Recommendation letter of "listing situation" -- courage is the most valuable
Coroutinecontext in kotlin
stm32F407-------ADC
[camera special topic] Hal layer - brief analysis of addchannel and startchannel
Cfdiv2 Fixed Point Guessing - (2 points for Interval answer)
Startup mode and scope builder of collaboration in kotlin
iptables 4层转发
Bottleneck period must see: how can testers who have worked for 3-5 years avoid detours and break through smoothly
RestCloud ETL 跨库数据聚合运算