tuk
tuk

Reputation: 6862

Is it necessary to synchronize read to a variable?

I am going through Java Concurrency in Practice. Can some explain me the following doubts I am having in the code in Listing 2.8 which is shown below:-

@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);
    }
}
  1. Is the getCacheHitRatio method necessary to be synchronized as the update to cacheHits and hits are from synchronized block and getCacheHitRatio is just reading the values?
  2. Why clone has been used in lastFactors and factors? Can't I just use factors=lastFactors? This has not been explained in the chapter.

Upvotes: 3

Views: 830

Answers (1)

Alex Suo
Alex Suo

Reputation: 3119

1) The synchronized in the writing side only guarantees that

1.1 When entering the code block, all the previous operations before the synchronized are done and written to main memory.

1.2 All the variables operated in the block have their value directly from main memory (i.e. all cache lines are refreshed).

1.3 At the end of the block, the altered variables are written into the main memory before quitting the block.

So when you read from another thread, you need synchronized to make sure it reads the latest value from the main memory, not from the thread cached value (i.e. the CPU cache line are successfully refreshed before used).

2) I don't know what's factors but I guess it's a shared object. If so and assignment operator in Java is just pointer assignment i.e. you still pointing to the same factors object; thus operating on it (read and write) still need synchronization.

Upvotes: 3

Related Questions