这是我的代码...
@immutable // This is not a standard annotation .Only for Showing that behavior of Class
class OneValueCached{
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;
public OneValueCached(BigInteger i,BigInteger[] factors){
lastNumber=i;
lastFactors=Arrays.copyOf(factors, factors.length);
}
public BigInteger[] getFactors(BigInteger i){
if(lastNumber==null || !lastNumber.equals(i))
return null;
else
return Arrays.copyOf(lastFactors, lastFactors.length);
}
}
@threadSafe // This is not a standard annotation .Only for Showing that behavior of Class
public class VolatileCachedFactorizer implements Servlet{
private volatile OneValueCached cache=new OneValueCached(null, null);
public void service(ServletRequest req, ServletResponce resp){
BigInteger i= extractFromRequest(req);
BigInteger[] factors=cache.getFactors(i);
if(factors==null){ // ---> line 1
factors=factor(i); // --> line 2
cache=new OneValueCached(i, factors);
}
encodeIntoResponse(resp,factors);
}
}
为什么根据书籍中的说法,VolatileCachedFactorizer类是线程安全的,但我的观点是:
1.在第1行如果2个线程同时到达该点,第一个线程
检查条件并发现factor=null,第二个线程
也在同一时间检查相同的条件,在第一个线程
暂停执行第2行之后,发现factor=null。并且两者都将创建新的OneValueCached
对象,那么这段代码如何是线程安全的?书中认为这是线程安全的。
谢谢
@threadSafe
是什么注解?它要么是一个打字错误,要么不是标准注解,因为标准命名约定应该是@ThreadSafe
(对于@immutable
也是一样)。 - Thomasreturn lastFactors=Arrays.copyOf(lastFactors, lastFactors.length);
看起来很奇怪。它做了一个假设性的内部数组副本,但是然后将内部状态重新赋值为它提供的同一个副本。这不再是防御性或不可变的。实际上,这是一个编译错误,因为lastFactors
是 final,对吗? - ThiloCached
很可能是指cache
。但是factor
方法又是什么呢? - Thilo