Re: HashMap vs linear table lookup
The safety in String's hashCode() case has nothing to do with whether
storing the value is atomic or not. Checking the value, then
calculating it, then storing it is not atomic.
Patricia Shanahan wrote:
On a machine with an atomic 32 bit store, which includes all systems on
which Java runs, any read of the hash field will either see 0x0000 or
0xABCD, and consistently use 0xABCD as hash code.
All right. Atomicity is important, but not sufficient for the safety of the
lazy initialization. I also pointed out that if the value is not
synchronized, the value might be set more than once. The safety also stems
from the idempotency. Without the idempotency, the atomicity wouldn't
guarantee correct reads without synchronization.
The point is that before there is a store, there is a read. One thread could
read zero and set the hashCode(). Let's say the calculated hashCode() is
0xCAFEBABE. So thread 1 sets the hashCode to that value. Meanwhile, another
thread reads the value. Because there is no synchronization, thread 2 also
sees zero as the value. Because the calculation is deterministic, it also
sets the hashCode to 0xCAFEBABE. Meanwhile thread 3 wants to use the
hashCode(). It, too, sees zero and calculates the value.
The store is atomic. The cycle of read, calculate and store is not atomic.
Because of that, a String without synchronization, such as by calculating the
hashCode during construction, might have its calculated hashCode() set more
It is also true, as Patricia and others point out, that a non-atomic write
would break lazy initialization without synchronization.