10、Java併發性和多執行緒-執行緒安全與不可變性
以下內容轉自http://ifeve.com/thread-safety-and-immutability/:
當多個執行緒同時訪問同一個資源,並且其中的一個或者多個執行緒對這個資源進行了寫操作,才會產生競態條件。多個執行緒同時讀同一個資源不會產生競態條件。
我們可以通過建立不可變的共享物件來保證物件線上程間共享時不會被修改,從而實現執行緒安全。如下示例:
public class ImmutableValue{ private int value = 0; public ImmutableValue(int value){ this.value = value; } public int getValue(){ return this.value; } }
請注意ImmutableValue類的成員變數value
是通過建構函式賦值的,並且在類中沒有set方法。這意味著一旦ImmutableValue例項被建立,value
變數就不能再被修改,這就是不可變性。但你可以通過getValue()方法讀取這個變數的值。
(譯者注:注意,“不變”(Immutable)和“只讀”(Read Only)是不同的。當一個變數是“只讀”時,變數的值不能直接改變,但是可以在其它變數發生改變的時候發生改變。比如,一個人的出生年月日是“不變”屬性,而一個人的年齡便是“只讀”屬性,但是不是“不變”屬性。隨著時間的變化,一個人的年齡會隨之發生變化,而一個人的出生年月日則不會變化。這就是“不變”和“只讀”的區別。(摘自《Java與模式》第34章))
如果你需要對ImmutableValue類的例項進行操作,可以通過得到value變數後建立一個新的例項來實現,下面是一個對value變數進行加法操作的示例:
public class ImmutableValue{ private int value = 0; public ImmutableValue(int value){ this.value = value; } public int getValue(){ return this.value; } public ImmutableValue add(int valueToAdd){ return new ImmutableValue(this.value + valueToAdd); } }
請注意add()方法以加法操作的結果作為一個新的ImmutableValue類例項返回,而不是直接對它自己的value變數進行操作。
引用不是執行緒安全的!
重要的是要記住,即使一個物件是執行緒安全的不可變物件,指向這個物件的引用也可能不是執行緒安全的。看這個例子:
public void 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類持有一個指向ImmutableValue例項的引用。注意,通過setValue()方法和add()方法可能會改變這個引用。因此,即使Calculator類內部使用了一個不可變物件,但Calculator類本身還是可變的,因此Calculator類不是執行緒安全的。換句話說:ImmutableValue類是執行緒安全的,但使用它的類不是。當嘗試通過不可變性去獲得執行緒安全時,這點是需要牢記的。
要使Calculator類實現執行緒安全,將getValue()、setValue()和add()方法都宣告為同步方法即可(下一節講解)。
==>如有問題,請聯絡我:easonjim#163.com,或者下方發表評論。<==
相關文章
- Java 併發和多執行緒(一) Java併發性和多執行緒介紹[轉]Java執行緒
- Java高併發與多執行緒(三)-----執行緒的基本屬性和主要方法Java執行緒
- 多執行緒與高併發(二)執行緒安全執行緒
- 併發與多執行緒之執行緒安全篇執行緒
- JAVA 併發之路 (二) 執行緒安全性Java執行緒
- 23、Java併發性和多執行緒-重入鎖死Java執行緒
- Java併發實戰一:執行緒與執行緒安全Java執行緒
- java多執行緒與併發 - 執行緒池詳解Java執行緒
- Java多執行緒/併發12、多執行緒訪問static變數Java執行緒變數
- 【重學Java】多執行緒進階(執行緒池、原子性、併發工具類)Java執行緒
- JAVA多執行緒併發Java執行緒
- 多執行緒安全性和Java中的鎖執行緒Java
- Java併發和多執行緒:序Java執行緒
- Java多執行緒/併發06、執行緒鎖Lock與ReadWriteLockJava執行緒
- 多執行緒與高併發(一)多執行緒入門執行緒
- Java多執行緒/併發08、中斷執行緒 interrupt()Java執行緒
- java併發與執行緒Java執行緒
- java多執行緒與併發 - 併發工具類Java執行緒
- Java高併發與多執行緒(二)-----執行緒的實現方式Java執行緒
- 【Java多執行緒】執行緒安全的集合Java執行緒
- 執行緒安全性執行緒
- Java 併發:執行緒、執行緒池和執行器全面教程Java執行緒
- java 多執行緒 併發 面試Java執行緒面試
- 可重入性和執行緒安全執行緒
- JAVA多執行緒和併發基礎Java執行緒
- 第10章:併發和分散式程式設計 10.1併發性和執行緒安全性分散式程式設計執行緒
- Java多執行緒中執行緒安全與鎖問題Java執行緒
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- 多執行緒併發篇——如何停止執行緒執行緒
- 併發程式設計之執行緒安全性程式設計執行緒
- 執行緒安全和不可重入執行緒
- 【多執行緒與高併發】- 執行緒基礎與狀態執行緒
- Java多執行緒——執行緒Java執行緒
- Java 多執行緒基礎(四)執行緒安全Java執行緒
- Java多執行緒與併發之ThreadLocalJava執行緒thread
- Java高併發與多執行緒(一)-----概念Java執行緒
- Java多執行緒與併發 - 瞭解“monitor”Java執行緒
- 執行緒與多執行緒執行緒