JavaMemoryModel: Intentional data race in String.hashCode()

From: Doron Rajwan (
Date: Wed Apr 14 2004 - 02:13:03 EDT

String.hashCode() in beta1 has intentional data race,
which is a good example of how a program can be
incorrectly-synchronized (according to the JMM), and
still be valid.

private int hash; // Default to 0
public int hashCode() {
    int h = hash;
    if (h == 0) {
        h = ...
        hash = h;
    return h;

Since the sources of Java are the #1 place to learn
Java, I think that this trick should be documented in
the code. Specifically:

1. The code is not correctly synchronized according to
the JMM.

2. It is done this way since volatile reads/writes
costs much more.

3. Each thread at will calculate the hash at most once
(the happens-before edge from the initialization to
the first write of each thread ensures that).

4. It would not work for long / double.

5. It would not work for objects, unless they are
immutable (all fields are final).

6. The hash value 0 is sacrificed. There is no way to
sacrifice a different value (by adding initializer),
or not to sacrifice any value at all (by adding a
boolean variable).

7. The code cannot be changed to (on volatile, it
could, although not recommended):
         if (hash != 0) return hash;


Doron Rajwan,

JavaMemoryModel mailing list -

This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:01:04 EDT