JAVA并发编程之volatile关键字

2019-08-29  本文已影响0人  躺在家里干活

volatile

修饰变量,直接存取原始内存的值;禁止指令重排序
volatile 百度百科

volatile可以保证内存的可见性

1.了解下线程内存和主内存的关系

Java线程内存和主内存图例

如图,每个线程都有自己单独的内存空间,储存着从主内存拷贝进来的副本,如果变量是共享变量(多个线程会用到),那么就会存在线程A和线程B中变量A的值不相同的情况。

2.volatile强制直接从原始内存中存取

int a = 变量A

此时变量A会直接从主内存中加载

变量A++

此时变量A会直接写回主内存

public class VolatileTest {
    //如果有volatile关键字程序会立即退出
    //如果没有volatile关键字,程序可能永远不会退出
    static volatile boolean isStop = false;

    /*boolean isStop = false;*/
    public void test() {
        Thread t = new Thread() {
            public void run() {
                while (!isStop) ;
            }
        };
        t.start();
    }

    public static void main(String args[]) throws InterruptedException {
        for (int i = 0; i < 25; i++) {
            new VolatileTest2().test();
        }
        isStop = true;
    }
}

运行上面的代码看看结果

3.volatile能够保证有序性(禁止指令重排序)

在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

/**
 * 一个简单的展示Happen-Before的例子.
 * 这里有两个共享变量:a和flag,初始值分别为0和false.在ThreadA中先给a=1,然后flag=true.
 * 如果按照有序的话,那么在ThreadB中如果if(flag)成功的话,则应该a=1,而a=a*1之后a仍然为1,下方的if(a==0)应该永远不会为真,永远不会打印.
 * 但实际情况是:在试验100次的情况下会出现0次或几次的打印结果,而试验1000次结果更明显,有十几次打印.
 */
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");
            }
        }
    }
}

上段代码引用博客[http://my.oschina.net/004/blog/222069?fromerr=ER2mp62C]

我的个人博客,有空来坐坐

上一篇下一篇

猜你喜欢

热点阅读