0
点赞
收藏
分享

微信扫一扫

spring单例模式,多例模式,饿汉模式,懒汉模式(二)?


上篇文章介绍了单例模式,多例模式,有不明白的同学可以点进去先观看:

​​spring单例模式,多例模式,饿汉模式,懒汉模式(一)?​​

这篇文章重点介绍饿汉模式懒汉模式,

饿汉模式:在加载对象时候,对象就会创建实例,为所有spring配置文件中定义的bean都是生成的一个实例,天生线程安全的,多线程的情况下也不会出现问题。

懒汉模式:在获取对象第一次请求的时候,才会创建实例。本身是线程不安全的,但有几种实现线程安全的写法。

1、饿汉模式:

因为实例被static和final修饰,在对象加载到内存的时候初始化,所以线程安全。

public class HungrySingleton {

private String name;

private static final HungrySingleton hungrySingleton = new HungrySingleton("张三");

public HungrySingleton(String name){
this.name = name;
}

public static HungrySingleton getInstance(){
return hungrySingleton;
}

}

虽然这样写线程安全,但他还是有缺陷的,在getBean实例之前,不能不给他设置属性和参数,这时候懒汉模式就出现了,可以通过双重检索可以实现线程安全。

2、懒汉模式:

private String name;
private static LazySingleton lazySingleton;

public LazySingleton(String name) {
this.name = name;
}

public static LazySingleton getInstance() {
//第一次访问的时候没有对象,所以获取对象
if (lazySingleton == null) {
lazySingleton = new LazySingleton("张三");
}
return lazySingleton;
}

public static LazySingleton getInstance2() {
//保证线程安全
synchronized (lazySingleton) {
if (lazySingleton == null) {
lazySingleton = new LazySingleton("张三");
}
}
return lazySingleton;
}

public static LazySingleton getInstance3() {
//保证线程安全,性能提升
if (lazySingleton == null) {
synchronized (lazySingleton) {
if (lazySingleton == null) {
lazySingleton = new LazySingleton("张三");
}
}
}
return lazySingleton;
}

懒汉模式可以通过双重效验和synchronized来实现线程安全

问:为什么要双重效验?从代码里我们可以看到

  1. getInstance()方法可以实现,第一次访问的时候没有对象,所以为null的时候,获取实例对象,但这种情况下多线程访问时候,会出现异常,导致创建多个实例,如何解决呢?
  2. getInstance2()方法可以保证线程安全,上锁之后,其他线程不可以进入,但这种情况会出现什么问题呢?会一直上锁,导致没必要的性能开销,实际只需要在第一次创建的上锁。
  3. getInstance3()这就是为什么要用双重效验,先判断是否为null,然后在用synchronized上锁实现线程安全。

最后,看到这里的读者,如果喜欢的话安排一波(点赞,收藏,关注),原创不易,每周定期分享小知识。

举报

相关推荐

0 条评论