Search code examples
javamultithreadingjava.util.concurrent

Is it possible to use the result of the last calculation directly ? Java Synchronized block


Why is the Synchronized block able to directly use the previous calculation result when two consecutive requests to factorize the same value?

code from 2-8 of Java Concurrency in Practice

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

}

Solution

  • I believe you have at least a race condition on your hand. It could be that a earlier issued factor(i) completes after a later issued factor(i); overwritting the value of the later issued factor(i). So the lastFactor and lastNumber could be updated to an earlier version. To resolve that problem I would add some checking in the last synchronized block.

    In the current code, you can have multiple threads doing the same calculation. I'm not sure if that is desirable.