本篇文章继续学习volatile。上篇文章简单的介绍了volatile和synchonized,这篇文章讲一下什么时候可以用volatile。

先看一段代码。

  1. package com.chzhao.voltiletest;
  2.  
  3. public class ChangeValue extends Thread {
  4.  
  5. public void run() {
  6. try {
  7. Thread.sleep(2000);
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. GlobalValues.STATUS = "stop";
  12. }
  13. }
  1. package com.chzhao.voltiletest;
  2.  
  3. public class VolatileDeep extends Thread {
  4.  
  5. public void run() {
  6. while (true) {
  7. try {
  8. Thread.sleep(1);
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. if (GlobalValues.STATUS.equals("stop")) {
  13. System.out.println(this.getName() + "stop");
  14. GlobalValues.STATUS = "running";
  15. }
  16. }
  17. }
  18.  
  19. public static void main(String[] args) {
  20. Thread t1 = new VolatileDeep();
  21. t1.setName("t1");
  22. t1.start();
  23.  
  24. Thread t2 = new VolatileDeep();
  25. t2.setName("t2");
  26. t2.start();
  27.  
  28. Thread t3 = new ChangeValue();
  29. t3.start();
  30. }
  31. }
  1. package com.chzhao.voltiletest;
  2.  
  3. public class GlobalValues {
  4. public static String STATUS = "running";
  5. }

这段代码很简单,输出的是什么呢?

输出的是 t1stop?

还是t2stop?

还是

t1stop
t2stop

?

真实的情况是以上三种都有可能。

因为变量STATUS不是线程安全的,做为一个状态标识,在多线程的情况下状态是不可知的。

但是,如果在变量前面加上volatile关键字。

  1. package com.chzhao.voltiletest;
  2.  
  3. public class GlobalValues {
  4. public volatile static String STATUS = "running";
  5. }

每次的都会输出

t1stop
t2stop

当然,顺序不定。

这说明,如果加了volatile关键字,作为标识状态是能够保证线程安全的。为什么呢?

《Java 理论与实践: 正确使用 Volatile 变量》中介绍:

  1. Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。

《深入理解Java虚拟机:JVM高级特性与最佳实践》中介绍:

  1. 当一个变量定义为volatile之后,它将具备两种特性,第一是保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。而普通变量不能做到这一点,普通变量的值在线程间传递均需要通过主内存来完成,例如,线程A修改一个普通变量的值,然后向主内存进行回写,另外一条线程B在线程A回写完成了之后再从主内存进行读取操作,新变量值才会对线程B可见。

关于主内存,以后会有文章介绍。

由上面两段文字可以知道,volatile有一个很好的特性-可见性,可以理解可见性是所有线程均可以立即得到变量的值。所以,在多线程情况下,用volatile修饰状态值是非常适合的。

参考资料:

《Java 理论与实践: 正确使用 Volatile 变量》

《深入理解Java虚拟机:JVM高级特性与最佳实践》

java volatile进阶(一)的更多相关文章

  1. 【搞定 Java 并发面试】面试最常问的 Java 并发进阶常见面试题总结!

    本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.觉得内容不错 ...

  2. 3.Java异常进阶

    3.JAVA异常进阶 1.Run函数中抛出的异常 1.run函数不会抛出异常 2.run函数的异常会交给UncaughtExceptionhandler处理 3.默认的UncaughtExceptio ...

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

    网上关于java volatile的资料已经不少了,但搜了好久也没看到谁用代码很好地验证过使不使用volatile的差异.最近自己写了个测试,意外的看到了两者的明显区别,为什么说意外呢,因为根据我的测 ...

  4. Java字符串进阶

    Java字符串进阶 前言 最常用的对字符串操作的类有三个,分别是String,StringBuilder,StringBuffer,下面将会详细的说说这三个类...... String String类 ...

  5. 总结:Java 集合进阶精讲2-ArrayList

    知识点:Java 集合框架图 总结:Java 集合进阶精讲1 总结:Java 集合进阶精讲2-ArrayList 初探: ArrayList底层结构是数组,是List接口的 可变数组的实现,所以会占用 ...

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

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

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

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

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

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

  9. 总结:Java 集合进阶精讲1

    知识点:Java 集合框架图 总结:Java 集合进阶精讲1 总结:Java 集合进阶精讲2-ArrayList 集合进阶1---为集合指定初始容量 集合在Java编程中使用非常广泛,当容器的量变得非 ...

随机推荐

  1. 转载:C++ STL set学习

    声明:本文转载自Penguin的博客 http://blog.sina.com.cn/s/blog_779cf3410101389s.html 1,set的含义是集合,它是一个有序的容器,里面的元素都 ...

  2. disable-linux-firewall-under-centos-rhel-fedora

    http://www.cyberciti.biz/faq/disable-linux-firewall-under-centos-rhel-fedora/

  3. ZOJ 3607 Lazier Salesgirl(贪心)

    题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3607 题意:一个卖面包的小姑娘,给第i个来买面包的人的价格是pi, ...

  4. Java注解实践

    Java注解实践 标签 : Java基础 注解对代码的语意没有直接影响, 他们只负责提供信息给相关的程序使用. 注解永远不会改变被注解代码的含义, 但可以通过工具对被注解的代码进行特殊处理. JDK ...

  5. SJ9012: IE6 IE7 不支持 JSON 对象

    标准参考 JSON 是一种数据交换格式,RFC 4627 对 JSON 进行了详细描述. 根据 ECMA-262(ECMAScript)第 5 版中描述,JSON 是一个包含了函数 parse 和 s ...

  6. uva 10047 The Monocycle(搜索)

    好复杂的样子..其实就是纸老虎,多了方向.颜色两个状态罢了,依旧是bfs. 更新的时候注意处理好就行了,vis[][][][]要勇敢地开. 不过这个代码交了十几遍的submission error,手 ...

  7. I.MX6 开启 1000Mb/s interface

    /*********************************************************************** * I.MX6 开启 1000Mb/s interfa ...

  8. Android如何调用第三方SO库

    问题描述:Android如何调用第三方SO库:已知条件:SO库为Android版本连接库(*.so文件),并提供了详细的接口说明:已了解解决方案:1.将SO文件直接放到libs/armeabi下,然后 ...

  9. XAMPP for Linux

     XAMPP 的 Linux 版图片集锦 安装过程仅 4 个步骤  步骤 1:下载 XAMPP PHP 5.4 XAMPP PHP 5.5  步骤 2:安装  步骤 3:开始运行  步骤 4:测试 使 ...

  10. 打印Ibatis最终的SQL语句

    在项目开发时都大家都希望将SQL在后台打印出来,以帮助开发以及后续的bug修改.如果用JDBC那么可以方便的打印,可使用ibatis就不知道怎么办了,最近在网上找了一段log4j的配置可以很保姆的处理 ...