Volatile详解

一,.volatile关键字的两层语义:

(一),一旦一个共享变量被volatile修饰之后,那么就具备了两层语义:

  1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

  2)禁止进行指令重排序。

 (二),内存屏障有两个能力:

      1. 阻止屏障两边的指令重排序

      2. 强制把写缓冲区/高速缓存中的脏数据等写回主内存,让缓存中相应的数据失效

 (三),volatile只保证可见性,不保证原子性;

  volatile方式的i++,总共是四个步骤:

  Load、Increment、Store、Memory Barriers。

(四)下面程序是:主线程修改非volatile类型的全局变量flag,子线程轮询flag,如果flag发生变动,则程序退出。但是如果实际运行这段代码会造成死循环,程序无法正常退出。这个现象是由于flag变量不是volatile的,主线程对flag的修改不一定能被子线程看到而引起的。

public class VisibilityDemo {
    private volatile   boolean flag=true;
    //private   boolean flag=true;
    
//-server -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=jit.log
    public static void main(String[] args) throws InterruptedException {
        VisibilityDemo demo1=new VisibilityDemo();
        new Thread(new Runnable() {
            @Override
            public void run() {
                int i=0;
                System.out.println(Thread.currentThread().getName());
                while(demo1.flag){
                    synchronized (this){

                        i++;

                    }
                }
                System.out.println(i);
            }
        }).start();
//        System.out.println("即将sleep的Thread是:"+Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(2);
        demo1.flag=false;
        System.out.println("被置为false了");
    }
}

加上volatile之后,程序正常退出,通过javap命令查看,有ACC_volatile命令,意思是禁止缓存。

遵循Happens-before原则。

 

posted @ 2020-05-05 18:43  Boogiever  阅读(356)  评论(0编辑  收藏  举报