aio*_*obe 8 java jvm memory-model jls
根据Java语言规范(例17.4-1),以下片段(从开始A == B == 0)...
Thread 1 Thread 2
-------- --------
r2 = A; r1 = B;
B = 1; A = 2;
Run Code Online (Sandbox Code Playgroud)
......可以导致r2 == 2和r1 == 1.这是因为执行的结果B = 1;不依赖于是否r2 = A已经执行,因此JVM可以自由地交换这两个指令的执行顺序.换句话说,规范允许以下交错:
Thread 1 Thread 2
-------- --------
B = 1;
r1 = B;
A = 2;
r2 = A;
Run Code Online (Sandbox Code Playgroud)
这显然导致r2 == 1和r1 == 1.
假设我们稍微调整一下这个例子:
Thread 1 Thread 2
-------- --------
r2 = A; r1 = B;
monitorenter obj monitorenter obj
monitorexit obj monitorexit obj
B = 1; A = 2;
Run Code Online (Sandbox Code Playgroud)
其中obj是线程之间共享的引用.
是的重新排序r2 = A,并B = 1仍然允许?
JLS说......
但是,允许编译器对任一线程中的指令重新排序,这不会影响该线程的执行.
...哪种类型的指示说明可能仍要交换.另一方面,以下声明
监视器上的解锁发生在该监视器上的每个后续锁定之前.
表明在某些调度中,我们可能在两个线程中的语句之间存在一个先发生的关系,这可能是不允许指令重新排序.
非正式地,这是不允许的。这被称为“蟑螂汽车旅馆模式”
http://jeremymanson.blogspot.com/2007/05/roach-motels-and-java-memory-model.html
特别是,动作不能跨同步块移动。
然而,从形式上来说,JMM 并没有谈论重新排序。在你的例子中,我们只能推断,
在总同步顺序中,同步块 1 位于同步块 2 之前,因此r2=A发生在之前A=2;必须为 0。但和r2之间没有约束;可以是 0 或 1。B=1r1=Br1
或者反之亦然。r1必须为 0,r2可以为 0 或 2。
所以程序仍然包含数据竞争;尽管如此,我们可以推断(r1,r2)只能是 (0,0), (1,0), (0,2);不可能是 (1,2)
| 归档时间: |
|
| 查看次数: |
163 次 |
| 最近记录: |