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");
            }
        }
    }
}

 

posted on 2018-04-06 20:03  爱不死  阅读(155)  评论(0编辑  收藏  举报