In JDK 1.6, Doug Lea uses final
preceding the next
field.
static final class HashEntry<K,V> {
final K key;
final int hash;
volatile V value;
final HashEntry<K,V> next;
Whereas in JDK 1.7, the next
field is preceded by volatile
. I also notice that in JDK 1.7, the get
method adopts getObjectVolatile
method to read the value
field, which has the volatile load semantics.
I have no sense why Doug Lea previously uses final
. If there are problems with correctness, then how could he replace it with volatile
in JDK 1.7(also JDK 1.8)?
Edit:
Specifically, my question is that could we replace final
with volatile
in JDK 1.6's implementation?
For your first question:
I have no sense why Doug Lea previously uses final. If there are problems with correctness, then how could he replace it with volatile in JDK 1.7(also JDK 1.8)?
It wasn't a matter of correctness. Both implementations are correct in terms of thread-safety. What was trying to be solved was reducing the initial footprint of the CHM. In Java 6, making the next
field final required the object be created with at least a place holder. This caused excessive empty object creation and so was changed to offer create-when-needed semantics.
Specifically, my question is that could we replace final with volatile in JDK 1.6's implementation?
Certainly as long as the operations continue to be sequentially consistent, which they are.
One of Doug Lea's comments touches on this design change
/*
* ...
* Historical note: The previous version of this class relied
* heavily on "final" fields, which avoided some volatile reads at
* the expense of a large initial footprint. Some remnants of
* that design (including forced construction of segment 0) exist
* to ensure serialization compatibility.
*/
So to answer another question you are probably having, why was final
chosen initially? To prevent some volatile reads later on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With