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