网上关于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而引起的多个线程读写公共变量不同步问题”的说法有误,只是参数不同而已

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

java volatile的一个验证反例(转)的更多相关文章

  1. Java并发编程之验证volatile不能保证原子性

    Java并发编程之验证volatile不能保证原子性 通过系列文章的学习,凯哥已经介绍了volatile的三大特性.1:保证可见性 2:不保证原子性 3:保证顺序.那么怎么来验证可见性呢?本文凯哥(凯 ...

  2. 一个具体的例子学习Java volatile关键字

    相信大多数Java程序员都学习过volatile这个关键字的用法.百度百科上对volatile的定义: volatile是一个类型修饰符(type specifier),被设计用来修饰被不同线程访问和 ...

  3. [Java并发编程(四)] Java volatile 的理论实践

    [Java并发编程(四)] Java volatile 的理论实践 摘要 Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 ...

  4. Java volatile关键字详解

    Java volatile关键字详解 volatile是java中的一个关键字,用于修饰变量.被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性. 简言之它的作用就是: 禁止指 ...

  5. java volatile进阶(一)

    本篇文章继续学习volatile.上篇文章简单的介绍了volatile和synchonized,这篇文章讲一下什么时候可以用volatile. 先看一段代码. package com.chzhao.v ...

  6. java volatile关键字的理解

    转载:http://shmilyaw-hotmail-com.iteye.com/blog/1672779 一个多线程的示例引发的问题 在讨论这个关键字之前先看一个多线程的示例代码: public c ...

  7. JAVA课程设计——一个简单的教务人事管理系统

    大三上学期期末总结,没错,上学期,写在下学期新学期开始,哈哈哈. 上学期学习了面向对象程序设计,课程设计的题目使用JAVA语言完成一个简单的教务人事管理系统,能够实现访问数据库的登录验证,分别按部门和 ...

  8. [Java并发编程(五)] Java volatile 的实现原理

    [Java并发编程(五)] Java volatile 的实现原理 简介 在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的 sync ...

  9. [Java并发编程(三)] Java volatile 关键字介绍

    [Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...

随机推荐

  1. Mysql insert声明优化

    1) 假设你同一时候从同一客户插入非常多行,使用多个值表的INSERT语句. 这比使用分开INSERT语句快(在一些情况中几倍).    Insert into test values(1,2),(1 ...

  2. SICP的一些个人看法

    网上搜书的时候,看到非常多人将这本书神话. 坦率地说,个人认为这本书过于学术化, 没什么实际project价值.一大堆题目也基本是高中数学竞赛题类似,浪费时间. 软件的核心技术是什么? 1>   ...

  3. C,C++中的static

    在C和C++中,static都有两种基本的含义,并且这两种含义经常是互相有冲突的: 1) 在固定的地址上分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次 函数调用时在堆栈上产生的.这也是 ...

  4. git tag使用

    #git tag command git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]       ...

  5. 【原创】leetCodeOj --- Interleaving String 解题报告

    题目地址: https://oj.leetcode.com/problems/interleaving-string/ 题目内容: Given s1, s2, s3, find whether s3  ...

  6. hdu1506——Largest Rectangle in a Histogram

    Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  7. 理解JavaScript的闭包

    在JS这块,免不了被问什么是闭包. 从一个常见的循环问题说起. 有一个ul列表, 里面有5个li标签,我希望点击每个li标签的时候,弹出每个li标签对应的索引值(第一个弹出0,第二个弹出1...). ...

  8. A simple Test Client built on top of ASP.NET Web API Help Page

    Step 1: Install the Test Client package Install the WebApiTestClient package from the NuGet Package ...

  9. 高榕资本宾悦:未使用的企业家Testin云测试服务类故障

    高榕资本岳斌:创业者未使用Testin云測试服务属不合格 2014/10/09 · Testin · 开发人员訪谈 Testin云測与工信部等联合承办的ICT中国.2014高层论坛之移动开发人员分论坛 ...

  10. 【 D3.js 进阶系列 — 1.1 】 其它表格文件的读取

    CSV 表格文件是以逗号作为单元分隔符的,其他还有以制表符 Tab 作为单元分隔符的 TSV 文件,还有人为定义的其他分隔符的表格文件.本文将说明在 D3 中怎样读取它们. 1. TSV 表格文件是什 ...