java volatile

volatile是Java提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制:synchronized 同步块(或方法)和 volatile 变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。
————————————————

volatile的特性

  1. 禁止指令重排序;
  2. 保证共享变量在多线程之间的可见性;
  3. 不保证操作的原子性(原子性操作是指: 此操作是逻辑上只需要执行一步,即可完成的最小的可执行单元,要么没执行、要么执行完成、不存在执行了一半的情况);

volatile的原理

加入volatile关键字之后,产生汇编代码之后,在该位置会有一个lock前置指令,相当于内存屏障,该屏障提供三个功能:
1:确保指令重排序时,不会将屏障前的操作排到屏障后,也不会将后边的操作排到屏障前。
2:强制对CPU缓存的修改立即写入内存
3:如果是写操作,让其他CPU对应的缓存无效

适用场景

  1. 轻量级的“读-写锁”策略:一线程写多线程读的变量
  2. 状态标记:动态修改标记的状态对线程接下来的逻辑进行控制
  3. 单例模式(双检查锁机制)

使用volatile的几个场景

状态标记

volatile boolean flag = false;
 //线程1
while(!flag){
    doSomething();
}
//线程2
public void setFlag() {
    flag = true;
}
//根据状态标记,终止线程。

单例模式中的double check

class Singleton {
	private volatile static Singleton instace;
	private Singleton() {}
	
	public static Singleton getInstance(){
	    //第一次null检查 ,利用volatile的线程间可见性,不需要加锁,性能提高    
	    if(instance == null){            
	        synchronized(Singleton.class) { //同步锁,阻塞其他线程
	            //第二次null检查,以保证不会创建重复的实例       
	            if(instance == null){
	                instance = new Singleton(); // 禁止重排序
	            }  
	        }           
	    }  
	    return instance;
    }
}

为什么要使用volatile 修饰instance?
instance = new Singleton(); 这并不是一个原子操作,编译成字节码指令一般是含有这两条指令:new,invokespecial(new指令顺序先于invokespecial指令),其中new用来分配对象内存空间并初始化默认值并返回堆对象的引用,而invokespecial指令用来调用对象自定义初始化方法,
这条语句instance = new Singleton(); 可以分解为三个步骤(正常指令顺序):

  1. memory = allocate(); // 给 instance分配内存空间
  2. <init>(memory); // 初始化对象 对应invokespecial调用对象自定义初始化方法(调用 Singleton 的构造函数来初始化成员变量)
  3. instance = memory ; // 将instance对象指向刚分配的内存空间地址引用(执行完这步 instance 就为非 null 了)。

在 JVM 的编译器中允许2和3之间的重排序(处理器重排序)。也就是说上面的第2步和第2步的顺序是不能保证的。如果3排在2的前面,则在3执行完毕(这时instance已经不是null 了)、2未执行之前(还没有完成对象的初始化),此时其他线程操作获取的将是未完全初始化的实例。而volatile通过禁止2和3的重排序而避免这种情况(3为volatile写)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值