[英]Happens-before mechanism in Java
我在Java中遇到過關於先發生機制的問題。 這是一個例子:
public class MyThread extends Thread {
int a = 0;
volatile int b = 0;
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
read();
}
public void write(int a, int b) {
this.a = a;
this.b = b;
}
public void read() {
System.out.println(a + " " + b);
}
}
這是事先發生的明顯例子,這是足夠安全的,正如我所知道的那樣。 a
將正確獲得新值,因為它在b
初始化之前。 但重新排序是否意味着安全性得不到保證? 我在說這個:
public void write(int a, int b) {
this.b = b;
this.a = a;//might not work? isn't it?
}
UPD主線程:
public class Main {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
t.start();
t.write(1, 2);
}
}
使b
變為volatile
並且在write
值設置為b
后將write
值設置為b
a
保證:
b
之前讀a
,然后 a
的值不會超過之前寫入b
時的值。 即,到寫入b
和從讀b
充當同步點,或圍欄,這意味着無論被寫入a
寫之前b
將從讀取后可讀b
(如果a
被寫入一次以上,以下寫入可能會或可能不會顯示)。
但是,您的代碼現在不安全。 在read
,您有以下表達式:
a + " " + b
在Java中, 表達式從左到右進行計算 。 這意味着, a
會前進行評估b
。 因此,它是完全可能的讀a
會看到一個舊值a
,同時的讀b
將看到一個新的值b
。 假如你有b
之前讀a
,之間發生,之前關系b
的寫入和讀取會覆蓋在寫a
,並從讀a
。 現在,它沒有。
至於write
重新排序操作 - 這將明顯消除b
的排序保證對a
操作過度a
,即使read
首先讀取b
然后讀取a
。
為了可視化事物,只給出b
是volatile
:
當前代碼不保證在 - 的操作順序 -
write a read a
write b --> happens before --> read b
重新排序write
使用給定的讀取不會為了a
,以及-
read a
write b --> happens before --> read b
write a
即使給定的read
是固定的, a
不會被責令b
-
write b --> happens before --> read b
write a read a
唯一安全的做法是保持當前write
並修復read
-
write a
write b --> happens before --> read b
read a
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.