1.线程安全3要素:原子性,可见性,禁止指令重排序
2.volatile保证线程的可见性,禁止指令重排序
3.volatile的一个使用场景:单例的双重检查加锁的实现,不使用volatile时,可能导致单例对象初始化不完整
创建对象的过程:
package com.test.threadlocal;
/**
* 创建对象的过程:
* 1.在堆里面开辟一块空间创建一个对象,并给变量里面的属性赋初始值,如果是int类型,就会为变量赋值0
* 2.对象的初始化,会把变量的值改为8
* 3.使用栈里面的变量指向堆内存里面的对象
*/
public class DoubleCheckLock {
int a = 8 ;
//volatile避免对象初始化不完整
private volatile static DoubleCheckLock dcl ;
private DoubleCheckLock(){
}
private static DoubleCheckLock getInstance(){
//防止已经创建了对象再去获取锁,消耗系统性能
if(dcl == null) {
//1.对象没有创建成功时,多个线程进入到这个位置
synchronized (DoubleCheckLock.class){
//2.已经创建对象释放锁后,1位置的线程拿到锁后进来,继续创建对象
if(dcl == null){
dcl = new DoubleCheckLock();
}
}
}
return dcl;
}
}
当创建对象的时候发生指令重排序,创建过程里面的2和3执行顺序调换,就会得到一个a=0的对象,正常的情况下应该获得一个a=8的对象