zoukankan      html  css  js  c++  java
  • 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+"\t"+vs[n].time2 +'\t' + vs[n].time1+'\t'+(vs[n].time2 - vs[n].time1)+'\n');
            }
            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而引起的多个线程读写公共变量不同步问题”的说法有误,只是参数不同而已

  • 相关阅读:
    LeetCode 67 Add Binary(二进制相加)(*)
    从头认识Spring-3.1 简单的AOP日志实现-某方法之前的前后记录日志
    Registration system
    BZOJ 1055 HAOI2008 玩具取名 动态规划
    9.Laravel5学习笔记:在laravel中注冊自己的服务到容器中
    B-Tree 索引和 Hash 索引的对照
    负载均衡之基于DNS负载
    Eclipse中git插件导入远程库和上传项目源代码到远程库
    Android开发艺术-第二章 IPC 机制
    一天教你入门struts2
  • 原文地址:https://www.cnblogs.com/trytocatch/p/2850002.html
Copyright © 2011-2022 走看看