[concurrency-interest] Does JDK 9 String.hashCode() have a bug?
Peter Levart
peter.levart at gmail.com
Wed Sep 28 06:33:08 EDT 2016
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/38190e8b/attachment.html>
More information about the Concurrency-interest
mailing list