是否可以直接使用上次计算的结果? Java 同步块
Is it possible to use the result of the last calculation directly ? Java Synchronized block
为什么连续两次请求对同一个值进行因式分解时,Synchronized块可以直接使用之前的计算结果?
代码来自 Java 并发实践
的 2-8
public class two_8_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;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
BigInteger i=extractFromRequest(req);
BigInteger[] factors=null;
synchronized (this) {
++hits;
if (i.equals(lastNumber)) {
++cacheHits;
factors = lastFactors.clone();
}
}
if (factors==null)
{
factors=factor(i);//question in here :Suppose two identical requests arrive here at the same time
synchronized (this)
{
lastNumber=i;
lastFactors=factors.clone();
}
}
encodeIntoResponse(res,factors);
}
}
我相信你手上至少有一个竞争条件。可能是较早发布的 factor(i)
在较晚发布的 factor(i)
之后完成;覆盖后来发布的值factor(i)
。所以 lastFactor 和 lastNumber 可以更新到更早的版本。为了解决这个问题,我会在最后一个同步块中添加一些检查。
在当前代码中,您可以让多个线程执行相同的计算。我不确定这是否可取。
为什么连续两次请求对同一个值进行因式分解时,Synchronized块可以直接使用之前的计算结果?
代码来自 Java 并发实践
的 2-8 public class two_8_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;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
BigInteger i=extractFromRequest(req);
BigInteger[] factors=null;
synchronized (this) {
++hits;
if (i.equals(lastNumber)) {
++cacheHits;
factors = lastFactors.clone();
}
}
if (factors==null)
{
factors=factor(i);//question in here :Suppose two identical requests arrive here at the same time
synchronized (this)
{
lastNumber=i;
lastFactors=factors.clone();
}
}
encodeIntoResponse(res,factors);
}
}
我相信你手上至少有一个竞争条件。可能是较早发布的 factor(i)
在较晚发布的 factor(i)
之后完成;覆盖后来发布的值factor(i)
。所以 lastFactor 和 lastNumber 可以更新到更早的版本。为了解决这个问题,我会在最后一个同步块中添加一些检查。
在当前代码中,您可以让多个线程执行相同的计算。我不确定这是否可取。