@ThreadSafe
public class CatchedFactorizer implements Servlet {
private BigInteger lastNumber;
private BigInteger[] lastFactors;
private long hits;
private long cacheHits;
public synchronized long getHits(){return hits;}
public synchronized double getCacheHitRatio(){
return (double)cacheHits/(double)hits;
}
public void service(ServeletRequest req,ServletResponse resp){
BigInteger i = extractFromRequest(req);
BigInteger [] factors = null;
synchronized (this) {
++hits;
if(i.equals(lastNumber)){
++cacheHits;
factors=lastFactors.clone();
}
}
if(factors==null){
factors=factor(i);
synchronized (this) {
lastNumber=i;
lastFactors = factors.clone();
}
}
encodeIntoResponse(resp,factors);
}
}
CachedFactorizer实现了在简单性(对整个方法进行同步)与并发性(对经可能短的代码路径进行同步)之间的平衡
。在获取与释放锁操作上都需要一定的开销,因此如果将同步代码块分的过细,那么效果并不好,尽管这样做不会破坏
原子性。当访问状态变量或者在符合操作的执行期间,cachedFactorize需要持有锁,但是在执行长时间的因数分解的
时候需要释放锁。这样既能保证线程的安全性,也不会过多的影响并发性,而且在每个同步代码块中的代码路径都“足够短”