• java volatile的一个验证反例(转)


        网上关于java volatile的资料已经不少了,但搜了好久也没看到谁用代码很好地验证过使不使用volatile的差异。最近自己写了个测试,意外的看到了两者的明显区别,为什么说意外呢,因为根据我的测试,在32位的JVM(以下均指oracle官方的JVM)上是看不出差异的,也就是说32位的JVM上,不会发生因为没使用volatile而引起的多个线程读写公共变量不同步问题(有误,见末尾的补充),偶然在64位的JVM上跑了下,问题一下出现了。我一直是用32位的JVM做测试,一直把问题的不出现归结于概率太低,所以没遇到,以致于我写了下面这个把这个小概率事件成倍放大的测试,但还是没看出差异,后来放到64位的JVM上,问题一下就出现了,程序直接不退出了

    复制代码
    /**
     * volatile关键字的测试
     * @author trytocatch
     * @date 2013-1-7
     */
    public class Volatile {
        long time1;//test运行时,使用两独立的变量来保存时间,避免因使用同步而对t1,t2造成影响
        long time2;
        volatile boolean boolValue=true;//volatile
        public static void main(String[] args) throws InterruptedException{
            int size=5000;//测试个数
            Volatile vs[]=new Volatile[size];
            long timeSum = 0;
            for(int n=0;n<size;n++)
                (vs[n]=new Volatile()).test();
    //        Thread.sleep(1000);
            for(int n=0;n<size;n++){//统计出,所有线程从boolValue变为false到while(boolValue)跳出所花时间的总和
                timeSum+=vs[n].time2 - vs[n].time1;
                System.out.print(n+"	"+vs[n].time2 +'	' + vs[n].time1+'	'+(vs[n].time2 - vs[n].time1)+'
    ');
            }
            System.out.println("响应时间总和(毫微秒):"+timeSum);
            long time1,time2;
            time1 = System.nanoTime();
    //        Thread.yield();
            time2 = System.nanoTime();
            System.out.println(time2-time1);//顺序执行两条语句的时间间隔,供参考
        }
    
        public void test() throws InterruptedException{
            Thread t2=new Thread(){
                public void run(){
                    while(boolValue)
                        ;
                    time2 = System.nanoTime();
                }
            };
            Thread t1=new Thread(){
                public void run(){
                    time1 = System.nanoTime();
                    boolValue=false;
                }
            };
            t2.start();
            Thread.yield();
            t1.start();
            t1.join();//保证一次只运行一个测试,以此减少其它线程的调度对 t2对boolValue的响应时间 的影响
            t2.join();
        }
    }
    复制代码

    至于我上面说的,在32位JVM上,不会发生因为没使用volatile而引起的多个线程读写公共变量不同步问题,因为我把测试的size增加到50000也没出一个问题,而且一放到64位JVM上,问题立马出现,所以可以断定是JVM的差异,至于为什么32位的JVM不会出问题,难道是它根本没做优化?希望JVM高手指点


    补充:今天在网上看到个资料,64位jvm只有server模式(server模式会进行更多的优化),32位JVM默认使用client模式,我将32位JVM设置为server模式后,问题同样出现了,平时不出现,是因为它根本就没做这方面的优化,所以,“在32位JVM上,不会发生因为没使用volatile而引起的多个线程读写公共变量不同步问题”的说法有误,只是参数不同而已

    http://www.cnblogs.com/trytocatch/archive/2013/01/07/2850002.html

  • 相关阅读:
    Linux下的输入/输出重定向
    strcpy与strncpy的区别
    C++的函数重载
    gtest 学习二
    gtest 学习一
    char* wchar* char wchar转换
    iconv 编译不通过问题
    嵌入式常用库
    驱动编程class_create说明
    libiconv 交叉编译
  • 原文地址:https://www.cnblogs.com/softidea/p/4982750.html
Copyright © 2020-2023  润新知