volatile保证可见性,防止指令重排序
参考文献 https://www.cnblogs.com/xll1025/p/6486170.html
相关知识点.
一、happen-before可见性原则
1.线程之间(访问共享数据)可见性共享,2锁,解锁后可见性hapen-before需要锁的线程;
3. volatile 被他修饰的数据,可见性写的动作happen-before 读的线程4,传递性A线程hapen-before B线程,B线程hapen-beforeC线程,则A hapen-before C.
public class VolatileExample extends Thread { //设置类静态变量,各线程访问这同一共享变量 private static boolean flag = false; public static void main(String[] args) throws Exception { new VolatileExample().start(); //sleep的目的是等待线程启动完毕,也就是说进入run的无限循环体了 Thread.sleep(100); flag = true; } //无限循环,等待flag变为true时才跳出循环 public void run() { while (!flag) { } ; } }
把变量加上 volatile 可以验证这个关键字的可见性!
二、防止重排序,指令重排遵守 as-if -seril
典型问题dcl 双重锁问题,具体问题不在阐述
这个例子比较好,测试出了重排序的效果
public class SimpleHappenBefore { /** 这是一个验证结果的变量 */ private static int a=0; /** 这是一个标志位 */ private static boolean flag=false; public static void main(String[] args) throws InterruptedException { //由于多线程情况下未必会试出重排序的结论,所以多试一些次 for(int i=0;i<1000;i++){ ThreadA threadA=new ThreadA(); ThreadB threadB=new ThreadB(); threadA.start(); threadB.start(); //这里等待线程结束后,重置共享变量,以使验证结果的工作变得简单些. threadA.join(); threadB.join(); a=0; flag=false; } } static class ThreadA extends Thread{ public void run(){ a=1; flag=true; } } static class ThreadB extends Thread{ public void run(){ if(flag){ a=a*1; } if(a==0){ System.out.println("ha,a==0"); } } } }