線程安全中的不變性(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卻沒有修改,那麼它們之間的不變性就被破壞了。多個變量存在不變性時,就需要在單個原子操作中更新所以相關的狀態變量。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章