这是关于volatile的一些细节的旁注说明。在这里写这个是因为评论太多了。我想举一些例子说明挥发性如何影响可见性,以及在jdk 1.5中如何改变。
给出以下示例代码:
public class MyClass{ private int _n; private volatile int _volN; public void setN(int i) { _n = i; } public void setVolN(int i) { _volN = i; } public int getN() { return _n; } public int getVolN() { return _volN; } public static void main() { final MyClass mc = new MyClass(); Thread t1 = new Thread() { public void run() { mc.setN(5); mc.setVolN(5); } }; Thread t2 = new Thread() { public void run() { int volN = mc.getVolN(); int n = mc.getN(); System.out.println("Read: " + volN + ", " + n); } }; t1.start(); t2.start(); }}
此测试代码的行为在jdk1.5 +中得到了很好的定义,但在jdk1.5 之前 并未得到 很好的定义。
在jdk1.5之前的世界中,易失性访问和非易失性访问之间没有定义的关系。因此,该程序的输出可能是:
- 读:0,0
- 读:0,5
- 读取:5,0
- 读:5、5
在jdk1.5 +世界中,volatile的语义已更改,因此volatile访问以与同步完全相同的方式影响非易失性访问。因此,在jdk1.5
+世界中只有某些输出是可能的:
- 读:0,0
- 读:0,5
- 读取:5,0 < -不可能
- 读:5、5
输出3是不可能的,因为从易失性_volN读取“ 5”会在2个线程之间建立一个同步点,这意味着从t1开始对t2 分配 必须 对_volN分配的所有 *** 作。
进一步阅读:
- 修复Java内存模型,第1部分
- 修复Java内存模型,第2部分
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)