线程安全中的不变性(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却没有修改,那么它们之间的不变性就被破坏了。多个变量存在不变性时,就需要在单个原子操作中更新所以相关的状态变量。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章