不同线程直接进行数据交互时,会经理8个步骤:
- Lock 把主内存中的变量标识为一条线程独占状态
- Read 把主内存中的变量读取到工作内存中
- Load 把变量放入变量副本中
- Use 把变量副本传递给线程使用
- Assign 把线程正在使用的变量传递到工作内存中的变量副本
- Store 把工作内存中的变量副本传递到主内存中
- Write 把变量副本作为一个变量放入主内存中
- UnLock 解除线程的独占状态
volatile是JVM提供的一个轻量级的同步机制,除了能够避免“JVM对long/double的误操作”外(JVM允许64位的long和double类型在执行load,store,read和write操作时,分成两次32位的原子性操作,这就意味着多个线程共享一个long或double类型时,某一个线程理论上可能读到半个long或double值,可以使用volatile关键字来避免jvm的误操作,但是目前主流的jvm都已经允许将64位的数据类型直接设置为原子性操作),还有以下两个作用
1、volatile修饰的变量可以对所有线程立即可见
不同线程如果要访问同一个变量,就必须借助主内存进行传递,但是如果个变量加了volatile关键字,则该变量的值就可以被所有线程即时感知,某一个线程对volatile变量进行的任何操作,都会在第一时间同步到其他线程中
2、volatile可以禁止指令进行重排序优化
真正意义上的单例模式
public class Singeton {
private volatile static Singeton instance=null;
private Singeton(){}
public static Singeton getInstance(){
if(instance==null){
synchronized (Singeton.class){
if(instance==null){
instance=new Singeton();
}
}
}
return instance;
}
}
此外,要特别注意的一点是,虽然volatile修饰的变量具有可见性,但是并不具备原子性,因此volatile不是线程安全的。要理解这点,就要明确区分原子性和重排序的概念:原子性是指某一条语句不可再拆分,重排序是指某一条语句内部的多个指令的执行顺序
如果要实现线程安全,可以使用java.util.concurrent.atomic包中提供的原子类型,该类通过实现CAS算法保证了原子性操作。
网友评论