java单例总dcl_关于单例的DCL方式分析

public classSingleton {/*** 单例对象实例*/

private volatile static Singleton instance = null;public staticSingleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {

instance= newSingleton();

}

}

}returninstance;

}

}

这是一个典型的DCL单例,其中volatile在之前已经说过了,可以保证无论何时读取这个变量,都是读到内存中最新的值,无论何时写这个变量,都可以立即写到内存中。

但是并没有这么简单,在没有见volatile修饰instance时,在编译后,编译器会自动把第二个判断删除,因为编译器判断这个程序在执行过程中,这个值是不会改变的,编译器不考虑多线程的情况。加了volatile,是告诉编译器,这个变量随时有可能会被其他线程改变,这样编译器就不会把这两个判断优化成一个判断了。

同时,volatile的变量,可以保证对该变量的操作具有原子性,典型的例子是long和double型变量,通常需要分两步读写一个double变量,volatile修饰的double可以保证对一个double变量的操作的两部分不会被多线程插入。以及对引用类型赋值的,new一个实例的过程不会被其他线程插入(new在编译指令中是分成几步执行的,防止这几步在执行过程中被其他线程取这个变量值,取到一个不完整的实例)。可以简单的理解为对volatile变量的set和get方法加上了synchronized关键字,在new的过程中,整个都处在set中,所以不会被其他线程的get打断,取到不完整的引用。

原子性针对一个long或者double或者一个引用类型,对于引用类型,原子性是指在new实例的过程中,不会被其他线程取到,即不会被其他线程取到一个不完整的实例。这种原子性可以理解为new的过程处于一个synchronize段的set方法中,只有set结束才可以被get到,即new的整个过程都是处于set中的。也可以理解为指令重排序,禁止把new过程的指令与把引用赋值给变量的语句重排序,赋值只发生在new结束之后。

再次,在第二次判断if (instance == null)的时候,会再次取一次instance,再次取这个instance已经是所有线程最新的,每次修改的引用都会实时反映到主内存中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值