美文网首页工作生活
单例模式与线程安全

单例模式与线程安全

作者: Mixqum | 来源:发表于2019-07-04 18:04 被阅读0次

转载
http://www.barryzhang.com/archives/521
https://www.jianshu.com/p/0442fb1e0c7c

  1. double check + volatile单例,保证线程安全
    double check : 指两次if (instance == null)的判断:
  • 外层 if(instance==null)检查,避免每次获取对象锁
  • 内层if(instance==null)检查,锁住对象,避免多线程的时候,对象被创建多个
    原子操作(atomic) : 就是不可分割的操作,在计算机中,就是指不会因为线程调度被打断的操作
    声明并赋值就不是一个原子操作
  // 不是原子操作
  int i = 1; 

指令重排 :计算机为了提高执行效率,会做的一些优化,在不影响最终结果的情况下,可能会对一些语句的执行顺序进行调整

volatile:其作用是禁止指令重排。因为对象创建的时候在JVM经历3个步骤:
1.分配内存
2.调用构造函数,初始化成员变量,创建实例
3.将实例指向内存
如果不加volatile,在多线程情况下,1-2-3并不会按顺序执行,比如出现实例非null(执行了1,2),另外一个线程进入第一层check时,拿到的是非空实例,但没有被分配内存(没执行3),导致出现错误(也就是没有被完全初始化就被其他线程使用了)。


/**
 * 演示 double check + volatile单例,保证线程安全
 */
public class StringUtil {
    // 在多线程环境中,volatile能保证共享变量的可见性以及一定程度的有序性

    // volatile关键字的一个作用是禁止指令重排,把instance声明为volatile之后,
    // 对它的写操作就会有一个内存屏障,这样,在它的赋值完成之前,就不用会调用读操作。
    // volatile 阻止的不是singleton = new Singleton()这句话内部[1-2-3]的指令重排,
    // 而是保证了在一个写操作([1-2-3])完成之前,不会调用读操作(if (instance == null))
    private volatile static StringUtil instance;

    private StringUtil(){

    }

    public static StringUtil getInstance(){
        // 先判断是否存在。避免每次获取锁,开销较大
        if(instance==null){
            synchronized (StringUtil.class){
                // 防止可能出现多个实例的情况
                if(instance==null){
                    instance = new StringUtil();
                }
            }
        }
        return instance;
    }
}
  1. 懒汉式单例 + 静态内部类 保证线程安全
    在第一次使用时,实例化对象
/**
 * 演示 懒汉式单例 + 静态内部类
 */
public class ToastUtil {

    private ToastUtil(){

    }

    static class  ToastHolder{
        private static ToastUtil instance = new ToastUtil();
    }

    public static ToastUtil getInstance(){
        return ToastHolder.instance;
    }
}

相关文章

  • 设计模式

    手写单例模式(线程安全) 你知道几种设计模式?单例模式是什么?Spring中怎么实现单例模式?

  • 设计模式(2) 单例模式

    单例模式 线程安全的Singleton 会破坏Singleton的情况 线程级Singleton 单例模式是几个创...

  • 面试复习-设计模式

    一、单例模式 确保一个类只有一个实例,并提供一个全局访问点。 线程不安全的单例模式 懒汉式 线程安全的单例模式: ...

  • 单例设计模式笔记

    记录几种单例模式写法。 饿汉模式(线程不安全) 懒汉模式(线程不安全) 懒汉锁模式(线程安全) 懒汉双重判断模式(...

  • Java 常用单例

    一、线程不安全的单例模式 二、线程安全且高效的单例模式 1.双重校验锁 2.静态内部类

  • 设计模式——单例模式

    单例模式 饿汉模式 懒汉模式 线程不安全的模式 线程安全模式 懒汉模式和饿汉模式的区别

  • 单例(Singleton)

    单例设计模式 单例模式的创建 饿汉式1 饿汉式2 懒汉式 优化后的懒汉式(线程安全): 饿汉式与懒汉式区别 单例模...

  • 实现单例模式的方式2

    方式一: 能保证线程安全 定义类的时候实现单例模式 方式二: 能保证线程安全 对已定义好的类实现单例模式

  • Java 单例模式

    概述 Java中单例模式是一种常见的设计模式,单例模式总共有7种写法。 懒汉,线程不安全 懒汉,线程安全 饿汉 饿...

  • 设计模式——单例模式的破坏

    概述: 之前学习了单例模式的几种实现,解决了多线程情况下,单例的线程安全问题,保证了单例的实现。但是单例模式在下面...

网友评论

    本文标题:单例模式与线程安全

    本文链接:https://www.haomeiwen.com/subject/sdgrhctx.html