我正在经历Java Concurrency in Practice。有些人可以解释一下我在清单2.8中的代码中遇到的以下疑问,如下所示: -
@ThreadSafe
public class CachedFactorizer implements Servlet {
@GuardedBy("this") private BigInteger lastNumber;
@GuardedBy("this") private BigInteger[] lastFactors;
@GuardedBy("this") private long hits;
@GuardedBy("this") private long cacheHits;
public synchronized long getHits() { return hits; }
public synchronized double getCacheHitRatio() {
return (double) cacheHits / (double) hits;
}
public void service(ServletRequest 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);
}
}
getCacheHitRatio
方法是否需要同步,因为cacheHits
和hits
的更新来自同步块,而getCacheHitRatio
只是读取值?clone
和lastFactors
中使用了factors
?我不能只使用factors=lastFactors
吗?这一点在本章没有解释。答案 0 :(得分:1)
1)写作方面的synchronized
仅保证
1.1进入代码块后,synchronized
之前的所有操作都完成并写入主存储器。
1.2块中操作的所有变量都直接来自主存储器(即刷新所有缓存行)。
1.3在块结束时,更改的变量在退出块之前写入主存储器。
因此,当您从另一个线程读取时,您需要synchronized
以确保它从主内存中读取最新值,而不是从线程缓存值中读取(即CPU缓存行在使用前已成功刷新)。
2)我不知道是什么因素,但我猜这是一个共享的对象。如果是这样,Java中的赋值运算符只是指针赋值,即你仍然指向相同的因子对象;因此对其进行操作(读取和写入)仍然需要同步。