Memory consistency errors發生在當不同的threads對它們要處理的相通資料以有非一致的看法,這造成memory
cosistency errors是非常複雜的,幸運地,程式設計師不需要瞭解造成這個原因的細節,所需要的只是要如何避免這
樣的情況發生的策略。
避免記憶體不一致錯誤的關鍵是瞭解happen-before relationship(發生之前關聯)
int counter = 0;
counter欄位被Thread A,B分享,假設Thread A增加counter,而Thread B快速的印出counter
System.out.println(counter);
如果兩個敘述被執行在同一個thread,我們可以安全假定被印出的值會是1,但是如果兩個敘述被執行在個別的threads
時,印出來的值就有可能是0,因為並沒有擔保thread A改變了counter對Thread B而言是可見的,除了程式設計師有
成立happen-before relationship在兩個敘述之間。
還有很多行為可以創造happen-before relationships, 其中一個就是synchronization。
我們已經看過兩種行為可以創造happen-before relationships
創造新thread的程式碼對新thread是可見的
同步方法
Java提供兩種基本的同步語法,synchronized methods和synchrnoized statements
讓發法能夠synchronized只要加上synchronized關鍵字在宣告時
public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } }
如果count是一個SynchronizedCounter的實例,這最造成兩種方法同步影響
第一,不可能同時引發兩個同步方法在同一個物件上,當一個thread正在執行一個同步方法在物件上,其他的thread只能
引發同步方法在同一個物件區塊直到第一個物件完成了他的動作。
第二,當一個同步方法存在,這會自動成立happens-before relationship給任何隨之而來的同步方法呼叫在同一個
物件上,這擔保物件的狀態改變是可視的。
注意建構子不能是是同步的!會造成語法上的錯誤。
注意當建構一個將會被分享在threads間的物件,早先地小心物件的參考沒有漏出,例如假設你想要維護一個List稱作
instances含有每一個class的實例,你可以嘗試增加一行程式碼
instances.add(this);
給建構子,但是其他的thread也可以使用instances在物件建構完成之前存取物件。
同步方法用簡單的策略避免thread interference以及memory consistency errors,如果一個物件被超過一個
以上的物件可視,所有的物件變數讀寫都要被完成用synchronized方法,這個方法相當有效率,但是可能會造成liveness
問題
No comments:
Post a Comment