首頁  >  文章  >  Java  >  java 線程安全與不可變性

java 線程安全與不可變性

黄舟
黄舟原創
2017-02-28 10:38:331515瀏覽

競態條件的發生只是在如果兩個執行緒同時存取相同的資源,以及一個或更多的執行緒寫這個資源。如果多個執行緒讀出這個相同的資源,競態條件不會發生。

我們可以確定,在線程之間共享的物件通過使得這個共享的物件不可變,不會被任何的線程更新,從而是線程安全的。這裡有一個例子:


public class ImmutableValue{

  private int value = 0;

  public ImmutableValue(int value){
    this.value = value;
  }

  public int getValue(){
    return this.value;
  }
}


注意對於ImmutableValue實例的value值是怎樣傳遞給這個建構子的。也要注意這裡沒有set方法。一旦這個實例被創建了,你就不能改變它的值了。它是不可變的。然而你可以使用get方法去讀取它。


如果你需要在這個事例上執行操作,你可以使用來自操作結果的值回傳一個新的實例。這裡也有一個例子:


public class ImmutableValue{

  private int value = 0;

  public ImmutableValue(int value){
    this.value = value;
  }

  public int getValue(){
    return this.value;
  }

  
      <strong>public ImmutableValue add(int valueToAdd){
      return new ImmutableValue(this.value + valueToAdd);
      }</strong>
  
}


注意,這個add方法返回一個新的實例伴隨著這個添加操作的結果,而不是添加這個值到它自己。


這個引用不是線程安全的

記住這個是重要的,甚至如果一個對象是不可變的,以及從而是線程安全的,對於這個物件的引用可能不是線程安全的。看這個範例:


public class Calculator{
  private ImmutableValue currentValue = null;

  public ImmutableValue getValue(){
    return currentValue;
  }

  public void setValue(ImmutableValue newValue){
    this.currentValue = newValue;
  }

  public void add(int newValue){
    this.currentValue = this.currentValue.add(newValue);
  }
}


這個Calculator類別持有一個上面物件的參考。注意它可能透過setValue方法和add方法改變那個引用。因此,甚至如果這個類別內部使用了一個不可變的對象,它本身就不是不可變的,因此不是線程安全的。換句話說:這個ImmutableValue類別是執行緒安全的,但是它的使用不是。這個就是需要記住的一些事情,什麼時間嘗試著透過不可變性來獲取線程安全。

為了讓Calculator類別執行緒安全,你應該在getValue(),setValue(),以及add()方法上使用synchronized關鍵字。那個將會有效果的。


 以上就是java 執行緒安全與不可變性的內容,更多相關內容請關注PHP中文網(www.php.cn)!


#
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn