[concurrency-interest] Does JDK 9 String.hashCode() have a bug?

David Holmes davidcholmes at aapt.net.au
Wed Sep 28 07:29:27 EDT 2016


I thought that one of the properties of the JMM is that a second read of a variable can not return an earlier write to that variable. Certainly it is a property I recall being discussed in JSR-133.

 

David

 

From: Concurrency-interest [mailto:concurrency-interest-bounces at cs.oswego.edu] On Behalf Of Peter Levart
Sent: Wednesday, September 28, 2016 8:33 PM
To: concurrency-interest <Concurrency-interest at cs.oswego.edu>
Subject: [concurrency-interest] Does JDK 9 String.hashCode() have a bug?

 

Hi,

I would like to discuss the implementation of String.hashCode() method in the light of JMM. Here it is (the recent one from JDK 9 which includes implementation of compact strings):

 

    public int hashCode() {
        if (hash == 0 && value.length > 0) {
            hash = isLatin1() ? StringLatin1.hashCode(value)
                              : StringUTF16.hashCode(value);
        }
        return hash;
    }

 

Here, 'hash' is a plain instance field in String. Suppose we have a freshly constructed non-zero length String object, whose reference 's' is accessible to two threads and each of them concurrently invokes hashCode() on it:

 

Thread 1:

int h1 = s.hashCode();

 

Thread 2:

int h2 = s.hashCode();

 

Suppose also that the isLatin1() ? StringLatin1.hashCode(value) : StringUTF16.hashCode(value) computation returns a non-zero value.

 

Is it possible that the outcome (h1, h2) is either (0, hc) or (hc, 0) where the hc is the non-zero result of above mentioned computation?

According to JMM, I think it is. Since there is no synchronization between a write w(hash, hc) by one thread and two reads r1(value):v1 and r2(value):v2 by the other thread that correspond to program lines:

    if (hash == 0 ....

and:

    return hash;

 

...the reads may or may not see the write independently. So there is a possibility that v1 == hc and v2 == 0.

 

Am I right and should this be fixed?

 

Note that JDK 8 code is different. It does not have this problem:

 

public int hashCode() {
        int h = hash;
        if (h == 0) {
            for (char v : value) {
                h = 31 * h + v;
            }
            if (h != 0) {
                hash = h;
            }
        }
        return h;
    }

 

Regards, Peter

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20160928/e35d33ce/attachment.html>


More information about the Concurrency-interest mailing list