美文网首页
JAVA并发编程之volatile关键字

JAVA并发编程之volatile关键字

作者: 躺在家里干活 | 来源:发表于2019-08-29 09:41 被阅读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]

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

    相关文章

      网友评论

          本文标题:JAVA并发编程之volatile关键字

          本文链接:https://www.haomeiwen.com/subject/flpbectx.html