差異處
這裏顯示兩個版本的差異處。
Both sides previous revision 前次修改 下次修改 | 前次修改 | ||
java:effective_java:concurrency:synchronize_access_to_shared_mutable_data [2020/02/17 00:54] tony |
java:effective_java:concurrency:synchronize_access_to_shared_mutable_data [2023/06/25 09:48] (目前版本) |
||
---|---|---|---|
行 2: | 行 2: | ||
====== Effective Java - Synchronize access to shared mutable data ====== | ====== Effective Java - Synchronize access to shared mutable data ====== | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | 這個Item主要在宣導「針對多執行緒會共享的變數,應該要Synchronize access;為了提高效能而不使用它,是非常危險且錯誤的。」要能寫出正確且效能好的程式碼,必須要了解原子性、有序性、可見性這三個特性。 | + | 這個Item主要在宣導「針對多執行緒會共享的變數,應該要Synchronize access;為了提高效能而不使用它,是非常危險且錯誤的。」要能寫出正確且效能好的程式碼,首先必須要了解原子性、有序性、可見性這三個特性: |
- | * 原子性: 對於共享變數的連續操作,必須確保全部都會被執行且不會被打斷。 | + | * 原子性: 對於共享變數的連續操作,必須確保全部都會被執行且不會被打斷。如果做到一半被打斷,結果當然就不會正確。 |
* 可見性: 某一執行緒對共享變數做了修改,另外一個變數在使用時,能夠立即拿到最新的數值。由於每個執行緒都有一份變數的資料備份,如果其中一個執行緒對變數做修改,當沒有做到可見性就會導致其它執行緒拿到舊的值。 | * 可見性: 某一執行緒對共享變數做了修改,另外一個變數在使用時,能夠立即拿到最新的數值。由於每個執行緒都有一份變數的資料備份,如果其中一個執行緒對變數做修改,當沒有做到可見性就會導致其它執行緒拿到舊的值。 | ||
* 有序性: 程式的執行結果必須和程式碼順序的執行結果相同。沒辦法確保有序性,是由於CPU為了提高程式的執行效率,做了代碼重排,在多執行緒時會有機會發生問題。 | * 有序性: 程式的執行結果必須和程式碼順序的執行結果相同。沒辦法確保有序性,是由於CPU為了提高程式的執行效率,做了代碼重排,在多執行緒時會有機會發生問題。 | ||
+ | 再來必須了解的是處理方法,最簡單的是直接使用synchronized去做mutual exclusion: | ||
+ | <code bash> | ||
+ | synchronized(mutex_object) { | ||
+ | // operations on the mutex_object | ||
+ | } | ||
+ | </code> | ||
+ | synchronized可以保證上面提到的三個特性,但最大的缺點就是無法被interrupted;如果可以的話,建議使用Lock相關的API。\\ | ||
+ | \\ | ||
+ | 另外常被誤用的就是volatile。volatile可以確保可見性與有序性,但它無法保證原子性,如果在多執行緒的存取下,一樣有可能造成不正確的結果。\\ | ||
+ | \\ | ||
+ | 最後一個要提的就是java.util.concurrent.atomic內的Atomic類。它是透過volatile加CAS(Compare and set)來達到thread-safe與lock-free的特性,因此往往能獲得比較好的效能: | ||
+ | <code java> | ||
+ | // Lock-free synchronization with java.util.concurrent.atomic | ||
+ | private static final Atomiclong nextSerialNum = new Atomiclong(); | ||
+ | public static long generateSerialNumber() { | ||
+ | return nextSerialNum.getAndIncrement(); | ||
+ | } | ||
+ | </code> | ||
+ | Effective Java只做了基本的介紹,如果要知道更進階的使用方法,我覺得「Java高併發編程詳解:多線程與架構設計」很不錯。 | ||
===== Note ===== | ===== Note ===== | ||
Effective Java第三版Item 78。 | Effective Java第三版Item 78。 |