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而引起的多个线程读写公共变量不同步问题”的说法有误,只是参数不同而已
http://www.cnblogs.com/trytocatch/archive/2013/01/07/2850002.html
java volatile的一个验证反例(转)的更多相关文章
- Java并发编程之验证volatile不能保证原子性
Java并发编程之验证volatile不能保证原子性 通过系列文章的学习,凯哥已经介绍了volatile的三大特性.1:保证可见性 2:不保证原子性 3:保证顺序.那么怎么来验证可见性呢?本文凯哥(凯 ...
- 一个具体的例子学习Java volatile关键字
相信大多数Java程序员都学习过volatile这个关键字的用法.百度百科上对volatile的定义: volatile是一个类型修饰符(type specifier),被设计用来修饰被不同线程访问和 ...
- [Java并发编程(四)] Java volatile 的理论实践
[Java并发编程(四)] Java volatile 的理论实践 摘要 Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 ...
- Java volatile关键字详解
Java volatile关键字详解 volatile是java中的一个关键字,用于修饰变量.被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性. 简言之它的作用就是: 禁止指 ...
- java volatile进阶(一)
本篇文章继续学习volatile.上篇文章简单的介绍了volatile和synchonized,这篇文章讲一下什么时候可以用volatile. 先看一段代码. package com.chzhao.v ...
- java volatile关键字的理解
转载:http://shmilyaw-hotmail-com.iteye.com/blog/1672779 一个多线程的示例引发的问题 在讨论这个关键字之前先看一个多线程的示例代码: public c ...
- JAVA课程设计——一个简单的教务人事管理系统
大三上学期期末总结,没错,上学期,写在下学期新学期开始,哈哈哈. 上学期学习了面向对象程序设计,课程设计的题目使用JAVA语言完成一个简单的教务人事管理系统,能够实现访问数据库的登录验证,分别按部门和 ...
- [Java并发编程(五)] Java volatile 的实现原理
[Java并发编程(五)] Java volatile 的实现原理 简介 在多线程并发编程中 synchronized 和 volatile 都扮演着重要的角色,volatile 是轻量级的 sync ...
- [Java并发编程(三)] Java volatile 关键字介绍
[Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...
随机推荐
- wbadmin delete backup删除服务器旧的镜像备份
- 清除Android工程中没用到的资源(转)
项目需求一改再改,UI一调再调,结果就是项目中一堆已经用不到但却没有清理的垃圾资源,不说工程大小问题,对新进入项目的人或看其他模块的代码的人来说,这些没清理的资源可能也可能会带来困扰,所以最好还是清理 ...
- android判断是否含有某权限
boolean has_permission = (PackageManager.PERMISSION_GRANTED == pkm.checkPermission("android.per ...
- 点击搜索取消UISearchDisplayController的搜索状态
一般,我们用到UISearchDisplayController的时候,都是须要对一个数据源进行刷选,在UISearchDisplayController自带的tableView中展示出来,然后点击退 ...
- uva 1393 - Highways(容斥原理)
题目连接:uva 1393 - Highways 题目大意:给定一个m∗n的矩阵,将矩阵上的点两两相连,问有多少条直线至少经过两点. 解题思路:头一次做这样的题目,卡了一晚上. dp[i][j]即为i ...
- poj 1962 Corporative Network
主题链接:http://poj.org/problem?id=1962 思路:每一个集合中用根节点标记这个集合,每一个点到根节点的距离. code: <span style="font ...
- QEMU-KVM自己主动创建虚拟机,以指定IP构造
正在使用qemu不能指定创建虚拟机的过程IP住址,然而,在实际应用中,我们需要有一台虚拟机IP住址,不是人为的虚拟机操作系统配置. 于qemu虚拟机技术文档(http://qemu.weilnetz. ...
- Godaddy Drupal Update
Godaddy对Drupal默认安装仅仅支持到7.22,眼下Drupal已经升级到7.28,安装完Drupal 7.22后,仅仅能手工升级. 安装Drupal在:https://hostingconn ...
- js 加载初始化日期
//初始化加载时间 $(function(){ var now = new Date(); var year = now.getFullYear(); //年 ...
- T-Sql(一)简单语法
原文:T-Sql(一)简单语法 Sql Server是鄙人学习的第一种数据库,对Sql Server有一种特别的情感,下面就说一下Sql Server的简单语法,适用初学者. 1,创建数据库creat ...