单例模式

单例模型

1.单例模式的定义

  确保一个类只有一个实例,并且可以自行实例化并向整个系统提供这个实例

2.单例模式的特点

  • 构造器私有
  • 自行构造实例
  • 通过共有的静态方法向外提供实例的获取

3.常用的两种单例模式

1. 懒汉式

package com.wxc.singleton.singleton4;

/**
*    懒汉式
*/
public class Singleton {

    private static volatile Singleton singleton = null;

    private Singleton() {

    }

    public static Singleton getSingleton() {
        if (singleton == null) {
                   singleton = new Singleton();          
          
        }
        return singleton;
    }
}

2. 饿汉式

package com.wxc.singleton.singleton4;

/**
*    懒汉式
*/
public class Singleton {

    private static volatile Singleton singleton = new Singleton();

    private Singleton() {

    }

    public static Singleton getSingleton() {          
        return singleton;
    }
}

4.存在的问题

	懒汉式在多线程环境下存在线程安全问题

5.改进的方案

1. 加锁

在getSingleton方法上加上synchronized或者方法内部加上synchronized。

2.双重检查锁定

package com.wxc.singleton.singleton4;

/**
 * 双重检查锁定
 */
public class Singleton {

    private static volatile Singleton singleton = null;

    private Singleton() {

    }

    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

3.关于双重检查锁定的解释

  如果第一次检查instance不为null的话,那么就不需要执行下面的初始化操作,也不需要加锁,因此可以大幅度降低synchronized带来的性能开销。
但是由于new instance()可能因为其编译器或处理器优化导致了指令的重排序,会导致代码读取到instance的引用不为null,但是instance所引用的对象可能还没完成初始化操作。
  new instance()实际上分为了3步
  1. memory = allocate(); // 1:分配对象的内存空间
  2. torInstance(memory); // 2:初始化对象
  3. instance = memory; // 3:设置instance指向刚分配的内存地址 // 注意,此时对象还没有被初始化!
但是由于指令重排序的原因,可能导致2和3位置交换了,此时使用volatile关键字修饰instance就可以很好的避免这个问题,因为volatile具有禁止指令重排序的功能。

posted on 2021-10-20 02:46  帅哥川  阅读(34)  评论(0编辑  收藏  举报

导航