Reputation: 141
Below is the code snippet from concurrency in practice.
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);
}
}
//Volatile is not enough to make VolatileCachedFactorizer thread safe? Why we need final specifier in OneValueCache.
public class VolatileCachedFactorizer implements Servlet {
private volatile OneValueCache cache = new OneValueCache(null, null);
//Servlet service method.
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
//Check factors are null or not.
if (factors == null) {
factors = factor(i);
cache = new OneValueCache(i, factors);
}
encodeIntoResponse(resp, factors);
}
}
What is the use of declaring fields as final in OneValueCache. "volatile OneValueCache cache" makes sure that object is visible to all the other threads and i assume that writes before volatile write is visible to all the other threads.
Upvotes: 2
Views: 1211
Reputation:
Final fields make OneValueCache immutable, thereby making it thread safe. They also have special semantics defined by the JLS, in particular, any thread will be able to see the correctly constructed object with the final fields initialized to its only correct value.
If this was not the case, and the fields happened to not be final, other threads might not be able to see the changes, even made in the constructor, because without final fields, there are no construction safety guarantees.
JCIP explains that OneValueCache is only an immutable reference class used to hold to the two bits of data. This is safer than updating two fields in the method, as it is not atomic. Then, OneValueCache is made volatile in the servlet because it needs to be changed, but is an atomic assignment, so no synchronization is needed.
Upvotes: 5
Reputation: 2017
It looks like the intention of OneValueCache class is to be immutable so declaring the values to be final just guarantees that at some later stage a programmer doesnt try to extend the class and overwrite the values.
Upvotes: 0
Reputation: 36304
They are two different things. Generally,
volatile
--> Creates a memory barrier which enforces the data in the cache to be flushed and forces data to be read from the main memory. So, all threads can always get the updated data for this particular field.
final
-->
for primitives --> specifies that the value cannot change
for non-primitives --> The references cannot change (i.e, reference cannot point to another object). For an object / field to be immutable, you need to ensure that it is transitively accessible by final fields and a reference of it doesn't escape.
PS : final and immutability are two different concepts. So, if you've heard of immutability, please understand that it is different from final.
Upvotes: 3