volatile的用法
来源:互联网 发布:mac c4d r17安装教程 编辑:程序博客网 时间:2024/06/07 11:00
参考资料:Java多线程发展简史
volatile在Java中用于保证可见性,但这么讲还是过于抽象。发现这篇文章里关于volatile的例子非常好,于是抄过来了
public class Volatile { public static void main(String[] args) { final Volatile volObj = new Volatile(); Thread t2 = new Thread() { public void run() { while (true) { volObj.check(); } } }; t2.start(); Thread t1 = new Thread() { public void run() { while (true) { volObj.swap(); } } }; t1.start(); } boolean boolValue;// use volatile to print "WTF!" public void check() { if (boolValue == !boolValue) System.out.println("WTF!"); } public void swap() { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } boolValue = !boolValue; }}
代码中存在两个线程,一个线程通过一个死循环不断在变换boolValue的取值;另一个线程每100毫秒执行“boolValue==!boolValue”,这行代码会取两次boolValue,可以想象的是,有一定概率会出现这两次取boolValue结果不一致的情况,那么这个时候就会打印“WTF!”。
但是,上面的情况是对boolValue使用volatile修饰保证其可见性的情况下出现的,如果不对boolValue使用volatile修饰,运行时就一次不会出现(起码在我的电脑上)打印“WTF!”的情形,换句话说,这反而是不太正常的,我无法猜测JVM做了什么操作,基本上唯一可以确定的是,没有用volatile修饰的时候,boolValue在获取的时候,并不能总取到最真实的值。
以上是原文中的分析。其实这里的分析还是有些小问题的,作者的意思是,使用 volatile
修饰 boolValue
,会打印 “WTF”;不使用 volatile
修饰 boolValue
,不会出现 “WTF”,认为这种现象不正常。
其实恰恰相反,这里的输出完全符合我们对 volatile 的预期,是正常现象。分析如下:
首先,check()
方法中 boolValue == !boolValue
这一句不是原子操作。简单地讲,不妨认为它至少包含两次读 boolValue 值的过程。
另外,看下图
如果有 volatile
修饰 boolValue
,则各个线程中的 var1, var2 均应与主存中的保持一致。在这个例子中就是,t1,t2线程中的boolValue均与主存中的一致。考虑以下执行过程(这里只是一种可能的上下文切换过程)
- t1 从主存中读 boolValue 值, 假定这时 boolValue 为 true
- t2 修改了主存中的 boolValue 值, 这时 boolValue 变成 false
- t1 再次从主存中读 boolValue 值,这时取到的值是 false
- t1 执行
==
操作进行判断, 显然 true == !false
所以会打印 “WTF”
反过来,如果没有 volatile
修饰 boolValue
,则上述过程很可能变成
- t1 从自己的内存副本中读 boolValue 值,假定这里 boolValue 为 true
- t2 修改线程内存副本中的 boolValue 值,这里的 boolValue 是变成什么值并不重要 (注意,这两个 boolValue 是不同的副本,所以互不影响)
- t1 再次从自己的内存副本中读 boolValue,这时取到的值是 true
- t1 执行
==
操作进行判断,显然 true != !true
所以这次不会打印 “WTF”
- volatile的用法
- volatile的用法
- volatile的用法。。
- volatile的用法
- volatile的用法(一)
- volatile的用法
- volatile的用法
- volatile的用法
- volatile的用法
- volatile的用法
- volatile关键字的用法
- 了解 volatile 的用法
- volatile的用法
- volatile的用法
- 关键字volatile的用法
- volatile的用法
- VOLATILE的用法
- volatile的用法
- 恶意卡TLE && 测评时判断OJ是否将TLE判成RE或WA
- c和c++的一些训练题(12)(继承问题)(子随父姓)
- C库函数_malloc calloc & realloc
- 分布式缓存--Memcached
- Java数据结构--- 二叉树(二叉排序树,层次遍历二叉树节点)
- volatile的用法
- 关于敏捷开发
- iOS XMPP研究探索:登录与注册
- VC2010工程基础设置——个人习惯
- MongoDB的增删改查
- (3.1.1)HTTP常见错误返回代码
- C#图片与string相互转换
- RFID第一次作业第一题
- Linux命令之head和tail