volatile
volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略
volatile内存语义
volatile是Java虚拟机提供的轻量级的同步机制。Java 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。但是volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。
volatile作用
1.保证被volatile修饰的共享变量对所有线程总是可见的,也就是当一个线程修改了一个被volatile修饰的共享变量的值,新值总是可以被其他线程立即得知。(可见性)
2.禁止指令重排序优化。(顺序性)
3.volatile 只能保证对单次读/写的原子性。i++ 这种操作不能保证原子性。
volatile的可见性
关于volatile的可见性作用,我们必须意识到被volatile修饰的变量对所有线程总是立即可见的,对volatile变量的所有写操作总是能立刻反应到其他线程中。
示例:
public class VolatileVisibilityExample {
public volatile boolean initFlag = false;
public void save() {
this.initFlag = true;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String threadname = Thread.currentThread().getName();
System.out.println("线程:"+threadname+":修改共享变量initFlag");
}
public void load(){
String threadname = Thread.currentThread().getName();
while (!initFlag){
//线程在此处空跑,等待initFlag状态改变
}
System.out.println("线程:"+threadname+"当前线程嗅探到initFlag的状态的改变");
}
public static void main(String[] args){
VolatileVisibilityExample example = new VolatileVisibilityExample();
Thread threadA = new Thread(()->{example.save();},"threadA");
Thread threadB = new Thread(()->{example.load();},"threadB");
threadB.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadA.start();
}
}
运行结果:
线程:threadA:修改共享变量initFlag
线程:threadB当前线程嗅探到initFlag的状态的改变
线程A改变initFlag属性之后,线程B马上感知到
volatile无法保证原子性
public class VolatileVisibility {
public static volatile int i =0;
public static void increase(){
i++;
}
}
volatile禁止重排优化