实践中的Java并发:清单3.12和3.13
我们有这些目标: //清单3.12实践中的Java并发:清单3.12和3.13,java,multithreading,concurrency,Java,Multithreading,Concurrency,我们有这些目标: //清单3.12 @Immutable class OneValueCache { private final BigInteger lastNumber; private final BigInteger[] lastFactors; public OneValueCache(BigInteger i, BigInteger[] factors) { lastNumber = i; lastFactors = Arra
@Immutable
class OneValueCache {
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;
public OneValueCache(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);
}
}
}
//清单3.13
@ThreadSafe
public class VolatileCachedFactorizer implements Servlet {
private volatile OneValueCache cache =
new OneValueCache(null, null);
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
if (factors == null) {
factors = factor(i);
cache = new OneValueCache(i, factors);
}
encodeIntoResponse(resp, factors);
}
}
书中说VolatileCachedFactorizer是线程保存。为什么?
例如:
这个流可以被认为是线程保存吗?我不明白什么?简短回答: 线程安全并不是绝对的。您必须确定所需的行为,然后询问实现是否为您提供了在多线程情况下所需的行为 更长的回答: 那么,这里想要的行为是什么?是因为总是给出正确的答案,还是因为如果两个线程连续请求它,它总是只实现一次 如果是后者——也就是说,如果你真的想节省每一点CPU——那么你是对的,这不是线程安全的。两个请求可以同时进入(或足够接近)以获得相同数字N的因子,如果计时成功,两个线程可能最终都会计算该数字 但是使用单值缓存,您已经有了重新计算已知内容的问题。例如,如果再次出现三个请求,例如N、K和N,该怎么办?对K的请求将使N处的缓存无效,因此您必须重新计算它 因此,这个缓存确实针对相同值的“条纹”进行了优化,因此,在该条纹中两次计算前几对(甚至很少!)答案的成本可能是可以接受的:作为回报,您得到的代码没有任何阻塞,并且非常容易理解
重要的是它永远不会给你错误的答案。也就是说,如果同时请求N和K,那么K的响应永远不会给出N的答案。这个实现为您提供了保证,所以我称之为线程安全。这是线程安全。最终目标是确保
服务
方法输出正确。OneValueCache始终保持lastNumber
和lastFactors
之间的正确关系