多线程案例之单例模式(饿汉模式、懒汉模式)

单例模式
1、设计模式:什么是设计模式?设计模式就是针对一些问题场景,大佬们总结除了一些固定的套路,按照这个套路实现代码。就会少走很多弯路。
2、常见的设计模式有两种:单例模式、工厂模式
单例模式中的代码的某个类只能有一个实例,不能有多个。
3、单例模式分为“饿汉”和“懒汉”两种。
4、饿汉模式:
在这里插入图片描述
在这里插入图片描述
这里的实例在类加载阶段就会直接创建实例。
5、懒汉模式-单线程版
我们一步步来看懒汉模式,首先与饿汉模式的区别是:在类加载的时候不创建实例,而是在用的时候在创建实例。
在这里插入图片描述
在这里插入图片描述
我们在这里并没有直接创建实例,而是在调用的时候才创建。
在这里插入图片描述
但是上述的懒汉模式的实现是线程不安全的,如果在首次创建实例的时候,多个线程同时调Getinstance方法,就可能导致创建出多个实例,我们上述说了单例模式只能有一个实例,所以我们加synchronized来解决这个问题:
在这里插入图片描述
这里在上述的代码上加锁,解决了多线程安全的问题。
我们还可以继续在此基础上继续改进:
在这里插入图片描述
上述画红圈的地方是改进的地方。
为什么要改进呢?
加锁解锁是一件开销比较高的事情,而懒汉模式的线程不安全只发生在首次创建实例的时候,后续使用的时候就不需要在进行加锁了。
改进的方法:
双重if:第一个if表示看instance是否已经被创建,同时我们还要避免“内存可见性”导致读取的instance出现偏差,于是加上volatile。“内存可见性”可以看我之间的博客-线程安全,里面有详细的解释什么叫“内存可见性”。
当我们多线程调用Getinstance方法的时候,就会产生锁竞争,由于我们已经加了synchornized,所以当某个线程竞争锁成功的时候,其他线程就会被第二层的if挡在外边,也不会继续创建新的实例。
举一个很简单的例子:
1)有三个线程, 开始执行 GetInstance , 通过外层的 if (instance == null) 知道了实例还没有创建的消息.开始竞争同一把锁.
2)其中线程1 率先获取到锁, 此时线程1 通过里层的 if (instance = null) 进一步确认实例是否已经创建. 如果没创建, 就把这个实例创建出来。
3)当线程1释放锁以后,线程2和3也拿到锁,通过里面的 if (instance = null) 来确认是否实例已经被创建,发现实例已经被创建了,就不再创建了。
4) 后续的线程, 不必加锁, 直接就通过外层 if (instance == null) 就知道实例已经创建了, 从而不再尝试获取锁了. 降低了开销.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值