JAVA併發編程筆記(2)

可見性

Visibility這玩意兒很微妙,很容易違反直覺。要在多線程之間讀寫內存保證可見性,需要使用同步:always use the proper synchronization whenever data is shared across threads.

Stale Data
public class MutableInteger {
    private int value;

    public int  get() { return value; }
    public void set(int value) { this.value = value; }
}

對於這個程序,即使對setter方法加上同步也是不夠的,其它讀的線程依然可能讀到修改之前或之後的數據。

對於64位的數字型變量,double或long,則不止是stale data的問題,因爲JVM會將64位的讀寫操作分成兩個32位的操作。所以有可能讀到完全錯誤的數據。

鎖和可見性

可以用鎖來保證可見性。Locking is not just about mutual exclusion; it is also about memory visibility. To ensure that all threads see the most up-to-date values of shared mutable variables, the reading and writing threads must synchronize on a common lock.

image

Volatile變量

也可以用volatile來保證可見性。要使用volatile變量,必須滿足下面三個條件

  1. Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value;
  2. The variable does not participate in invariants with other state variables; and
  3. Locking is not required for any other reason while the variable is being accessed.

鎖既能保證原子性又能保證可見性,而volatile只能保證可見性。volatile最常用在表示完成、中斷或者狀態這樣的標誌位上。volatile不能保證像count++這種計數器的作用,除非能肯定只有一個線程去更新它。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章