image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

单例模式

懒汉式

image.png

懒汉式改进1---synchronized

image.png

加synchronized 在 11行代码上,注意synchronized加在static上锁的是LazySingleton这个类的class文件,而如果加的这个方法不是静态的,那么锁的是在堆内存中生成的对象

即加在static上的synchronized等价于如下:


image.png

因为加入了synchronized这种大范围的锁,所以在性能上有一定的消耗

懒汉式改进2---双重校验锁

image.png
image.png
image.png

两种方式解决重排序: 1.加volatile关键字 2.不允许其他线程看到当前线程的重排序

单例模式---静态内部类

image.png
public class StaticInnerClassSingleton{
  private static class InnerClass {
    private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
  
 }
public static StaticInnerClassSingleton getInstance() {
    return InnerClass.staticInnerClassSingleton; 
  }
}
//必须私有构造器
private StaticInnerClassSingleton(){
}

原理,JVM在初始化一个类时,会对多个线程同步一个类的锁---即class对象的初始化锁,假设这时线程0获取到了这个锁,那么线程1是无法看到线程0在初始化这个类对象的内部操作(重排序)

饿汉式

在类加载的时候就完成了初始化,避免线程同步问题,缺点,没有延迟加载效果

public class HungrySingleton() {
 private final static HungrySingleton hungrySingleton = new HungrySingleton();
   private HungrySingleton(){}
public static HungrySingleton getInstance() {
   return hungrySingleton;
  }
}

单例的破坏和解决

如果单例模式中存在序列化和反序列化 那么单例模式会被破坏
即 用单例模式序列化到文件里,再反序列化文件出来的对象 和原先的对象不是同一个对象

解决方案: 在单例模式加上下面方法(以上面的饿汉式为例):

private Object readResolve(){
    return hungrySingleton;
}

防止反射攻击,在构造器加上判断,以上面的饿汉式为例:


image.png

未完----

收藏
评论加载中...