gpt4 book ai didi

Java 并发实践 : Listing 3. 12 和 3.13

转载 作者:行者123 更新时间:2023-11-30 08:09:20 24 4
gpt4 key购买 nike

我们有这些对象:

// list 3.12

@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);
}
}
}

// list 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是线程保存的。为什么?

例如:

  1. 线程A读取cache.getFactors(i);
  2. 然后线程B读取cache.getFactors(i);
  3. 然后线程B写入缓存。
  4. 然后线程A写入缓存。

这个流程可以算线程保存吗?我有什么不明白的?

最佳答案

简答:

线程安全并不是真的绝对。您必须确定所需的行为,然后询问实现是否为您提供在多线程存在的情况下的行为。

更长的答案:

那么,这里需要的行为是什么?只是总是给出正确的答案,还是如果两个线程连续请求它总是恰好执行一次?

如果是后者——也就是说,如果你真的想节省 CPU 的每一位——那么你是对的,这不是线程安全的。两个请求可以同时进入(或足够接近)以获得相同数字 N 的因式,如果计时成功,两个线程最终都可以计算出该数字。

但是对于单值缓存,您已经遇到了重新计算已知事物的问题。例如,如果收到三个请求,分别是 N、K 和 N,会怎样?对 K 的请求会使 N 处的缓存失效,因此您必须重新计算它。

因此,此缓存确实针对相同值的“连续”进行了优化,因此两次计算该连续中的前几个(甚至几个!)答案的成本可能是可以接受的成本:作为返回,您将获得没有任何阻塞且非常易于理解的代码。

重要的是它永远不会给您错误的答案。也就是说,如果您同时请求 N 和 K,则 K 的响应永远不会为您提供 N 的答案。此实现为您提供了保证,因此我将其称为线程安全。

关于Java 并发实践 : Listing 3. 12 和 3.13,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32531621/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com