Java多线程-volatile关键字
关键字 volatile 的作用主要有两个:
1)使变量线程间可见;
2)禁止指令重排序(CPU和编译器为了提升程序的执行效率, 通常会按照一定的规则对指令进行优化, 如果两条指令互不依赖, 则有可能它们执行的顺序并不是源代码编写的顺序)。
因私有堆栈和公共堆栈值不同导致的死循环
示例:
public class VolatileTest1 { public static void main(String[] args) throws InterruptedException { RunThread thread = new RunThread(); thread.start(); Thread.sleep(1000); thread.setRunning(false); System.out.println("已经赋值为 false"); } static class RunThread extends Thread { private boolean isRunning = true; public boolean isRunning() { return isRunning; } public void setRunning(boolean isRunning) { this.isRunning = isRunning; } @Override public void run() { System.out.println("进入run了"); while (isRunning == true) { } System.out.println("线程被停止了"); } } }
运行结果:
可以看到,结果进入死循环了。原因是 thread 线程一直在拿它自己线程的私有栈中的 isRunning 的值来判断,而 threa.setRunning(false) 虽然被执行,但是更新的却是公共堆栈中的 isRunning。
解决方案,就是为 isRunning 加上 valotile 修饰,让 thread 线程每次拿 isRunning 的值,都是公共堆栈中拿取
线程私有堆栈
volatile变量读取公共内存
变量在内存中的工作过程
synchornized 和 volatile 对比
1)关键字volatile 是线程同步的轻量级实现,所以 volatile 性能比 synchronized 要好,并且 volatile 只能修饰变量,synchronized 可以修饰方法 和 代码块
2)多线程访问 volatile 不会发生阻塞,而 synchronized 会出现阻塞
3)volatile 保证数据的可见性,但不能保证数据的原子性; 而 synchronized 保证了原子性,也可以间接保证可见性