線程安全中的不變性(Invariant)
多線程環境下,如果一個類的幾個變量之間存在不變性(Invariant),需要使用同步確保不變性不會被破壞。不變性是幾個變量之間的邏輯關係(logical assertion),不管按照什麼順序,不管哪個線程操作後,這個關係要保持不變,否則程序就會出錯。
在<<Java Concurrency in Practice>>舉了一個例子。一個類設計來求解一個整數的因式分解,多個線程會訪問這個類,爲了提高響應,存放了最近的整數和因素分解的結果。
class CachedFactorizer{
private int lastNumber;
private []Integer lastFactors;
public Integer[] factorizeInt(int number ){
Integer[] factors = null;
synchronized(this){
if(number == lastNumber){
//must clone. if just use factors = lastFactors, it is possible that some thread change lastFactors before return factors.
factors = lastFactors.clone();
}
}
if(factors == null){
factors = factorize(number);
synchronized(this){
lastNumber = number;
//must clone. factors is a auto variable, it is possible to be released after end calling the function.
//lastFactors could refer to a invalid space.
lastFactors = factors.clone();
}
}
return factors;
}
public static Integer[] factorize(int number){
Integer [] factors=null;
if(number>1){
ArrayList<Integer> result = new ArrayList<Integer>();
for(int i=2;i<number;i++){
while(number != i){
if(number%i != 0){
break;
}
result.add(i);
number = number/i;
}
}
result.add(number);
result.toArray((factors=new Integer[result.size()]));
}
return factors;
}
}
變量lastNumber和lastFactors之間就存在明顯的不變性,就是:lastFactors存放的數確實是lastNumber的因素。如果沒有正確使用同步,lastNumber已經修改,而lastFactors卻沒有修改,那麼它們之間的不變性就被破壞了。多個變量存在不變性時,就需要在單個原子操作中更新所以相關的狀態變量。
在<<Java Concurrency in Practice>>舉了一個例子。一個類設計來求解一個整數的因式分解,多個線程會訪問這個類,爲了提高響應,存放了最近的整數和因素分解的結果。
class CachedFactorizer{
private int lastNumber;
private []Integer lastFactors;
public Integer[] factorizeInt(int number ){
Integer[] factors = null;
synchronized(this){
if(number == lastNumber){
//must clone. if just use factors = lastFactors, it is possible that some thread change lastFactors before return factors.
factors = lastFactors.clone();
}
}
if(factors == null){
factors = factorize(number);
synchronized(this){
lastNumber = number;
//must clone. factors is a auto variable, it is possible to be released after end calling the function.
//lastFactors could refer to a invalid space.
lastFactors = factors.clone();
}
}
return factors;
}
public static Integer[] factorize(int number){
Integer [] factors=null;
if(number>1){
ArrayList<Integer> result = new ArrayList<Integer>();
for(int i=2;i<number;i++){
while(number != i){
if(number%i != 0){
break;
}
result.add(i);
number = number/i;
}
}
result.add(number);
result.toArray((factors=new Integer[result.size()]));
}
return factors;
}
}
變量lastNumber和lastFactors之間就存在明顯的不變性,就是:lastFactors存放的數確實是lastNumber的因素。如果沒有正確使用同步,lastNumber已經修改,而lastFactors卻沒有修改,那麼它們之間的不變性就被破壞了。多個變量存在不變性時,就需要在單個原子操作中更新所以相關的狀態變量。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.