Java并发编程之五:Volatile关键字(上)
来源:互联网 发布:惠普扫描软件下载 编辑:程序博客网 时间:2024/05/20 07:18
出处:http://blog.csdn.NET/ns_code/article/details/17101369
volatile用处说明
在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要。
示例程序
下面给出一段代码,通过其运行结果来说明使用关键字volatile产生的差异,但实际上遇到了意料之外的问题:
按照以上的理论来分析,由于value变量不是volatile的,因此它在main线程中的改变不会被Thread-0线程(在main线程中新开启的线程)马上看到,因此Thread-0线程中的while循环不会直接退出,它会继续判断missedIt的值,由于missedIt是volatile的,当main线程中改变了missedIt时,Thread-0线程会立即看到该变化,那么if语句中的代码便得到了执行的机会,由于此时Thread-0依然没有看到value值的变化,因此,currValue的值为10,继续向下执行,进入同步代码块,因为进入前后要将该线程内的变量值与共享内存中的原始值对比,进行校准,因此离开同步代码块后,Thread-0便会察觉到value的值变为了50,那么后面的valueAfterSync的值便为50,最后从break跳出循环,结束Thread-0线程。
意料之外的问题
但实际的执行结果如下:
从结果中可以看出,Thread-0线程并没有进入while循环,说明Thread-0线程在value的值发生变化后,missedIt的值发生变化前,便察觉到了value值的变化,从而退出了while循环。这与理论上的分析不符,我便尝试注释掉value值发生改变与missedIt值发生改变之间的线程休眠代码Thread.sleep(5000),以确保Thread-0线程在missedIt的值发生改变前,没有时间察觉到value值的变化。但执行的结果与上面大同小异(可能有一两行顺序不同,但依然不会打印出if语句中的输出信息)。
问题分析
在JDK1.7~JDK1.3之间的版本上输出结果与上面基本大同小异,只有在JDK1.2上才得到了预期的结果,即Thread-0线程中的while循环是从if语句中退出的,这说明Thread-0线程没有及时察觉到value值的变化。
这里需要注意:volatile是针对JIT带来的优化,因此JDK1.2以前的版本基本不用考虑,另外,在JDK1.3.1开始,开始运用HotSpot虚拟机,用来代替JIT。因此,是不是HotSpot的问题呢?这里需要再补充一点:
JIT或HotSpot编译器在server模式和client模式编译不同,server模式为了使线程运行更快,如果其中一个线程更改了变量boolean flag 的值,那么另外一个线程会看不到,因为另外一个线程为了使得运行更快所以从寄存器或者本地cache中取值,而不是从内存中取值,那么使用volatile后,就告诉不论是什么线程,被volatile修饰的变量都要从内存中取值。《内存栅栏》
但看了这个帖子http://segmentfault.com/q/1010000000147713(也有人遇到同样的问题了)说,尝试了HotSpot的server和client两种模式,以及JDK1.3的classic,都没有效果,只有JDK1.2才能得到预期的结果。
哎!看来自己知识还是比较匮乏,看了下网友给出的答案,对于非volatile修饰的变量,尽管jvm的优化,会导致变量的可见性问题,但这种可见性的问题也只是在短时间内高并发的情况下发生,CPU执行时会很快刷新Cache,一般的情况下很难出现,而且出现这种问题是不可预测的,与jvm, 机器配置环境等都有关。
姑且先这么理解吧!一点点积累。。。
正确的分析在这里:http://blog.csdn.net/ns_code/article/details/17382679
这里附上分析结果时参考的帖子及文章
http://segmentfault.com/q/1010000000147713
http://www.iteye.com/problems/98213
http://www.oldcaptain.cc/articles/2013/08/21/1377092100971.html
- Java并发编程之五:Volatile关键字(上)
- (五)java并发编程--volatile关键字
- Java并发编程:volatile关键字解析(五.使用volatile关键字的场景)
- Java并发编程之volatile关键字解析
- Java并发编程之volatile关键字解析
- java并发编程之volatile关键字解析
- Java并发编程之volatile关键字解析
- java 并发编程之volatile关键字
- Java并发编程之volatile关键字解析
- Java并发编程之六:Volatile关键字(下)
- java并发编程 -volatile关键字
- java并发编程---volatile关键字
- java并发编程volatile关键字
- Java并发编程:volatile关键字
- Java并发编程------volatile关键字
- java并发编程之synchronized关键字(五)
- JAVA并发编程4_线程同步之volatile关键字
- Java并发编程之volatile关键字的理解
- Postgresql数据库的一些字符串操作函数
- mybatis查询日期范围的记录数
- 怎样在 Ubuntu 中修改默认程序
- opencv2笔记02-调用findContours后错误解决方法(HeapValidate)
- Aes使用Java加密C#解密
- Java并发编程之五:Volatile关键字(上)
- form表单load成功后的如何触发事件
- java8总结(未完)
- 怎样清理Mac Book 里的其他中的内容?
- PostgreSQL学习手册(常用数据类型)
- linux下的DIR,dirent,stat
- LeeetCode 328. Odd Even Linked List 解题报告
- 浅谈数据库索引
- 关于js中的单线程和异步事件同操作系统的生产者消费者模型的理解