From: Andreas Leitgeb on
Tom Anderson <twic(a)urchin.earth.li> wrote:
> On Sun, 18 Jul 2010, Andreas Leitgeb wrote:
>> Actually, I do think, this *is* thread-safe.
> Nope.

You're right.
I noticed shortly after sending the first one off (as it always
happens, no matter how intensively one reviews one's posting
before sending) and have written a correction followup, already.

From: Joshua Cranmer on
On 07/18/2010 08:27 AM, Tom Anderson wrote:
> The beauty of the String approach, of using a special value of code to
> indicate that it had not been calculated, is that you don't need any
> synchronisation for safety, just the JLS's guarantee of no word tearing
> in writes and reads of int variables. Because it combines the flag and
> value fields in a single int, they are read and written atomically as a
> pair. Of course, were you to do this, you might want to avoid String's
> ability to generate a code which looks like a flag indicating the lack
> of a code (ie 0). But then, you might think the one in four billion
> chance of it happening was insignificant.

Or you could store the value in the low word of a long and the flag in
the upper word.

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth
From: Andreas Leitgeb on
Tom Anderson <twic(a)urchin.earth.li> wrote:
> To make this method safe, you either have to synchronize the whole thing,
> or do the update of calculated and code atomically at the end.

I'd have expected that if "calculated" was assigned *after* "code", that
would suffice without further synchronisation or volatile-ity of the fields.

Am I still too naive?

> The beauty of the String approach, of using a special value of code to
> indicate that it had not been calculated, is that you don't need any
> synchronisation for safety, just the JLS's guarantee of no word tearing in
> writes and reads of int variables. Because it combines the flag and value
> fields in a single int, they are read and written atomically as a pair. Of
> course, were you to do this, you might want to avoid String's ability to
> generate a code which looks like a flag indicating the lack of a code (ie
> 0). But then, you might think the one in four billion chance of it
> happening was insignificant.

I guess, I'd have spent one "if (h==0) { h=42; }" just before "hash = h;"
After the calculation loop, that extra "if" really wouldn't have hurt.

Has anyone found e.g. an english dictionary-word with hashCode 0, yet?
Or perhaps the name of some commonly used class in Java standard library
or some other String likely occurring in innocent code?

From: Lew on
Tom Anderson wrote:
>> The beauty of the String approach, of using a special value of code to
>> indicate that it had not been calculated, is that you don't need any
>> synchronisation for safety, just the JLS's guarantee of no word tearing
>> in writes and reads of int variables. Because it combines the flag and
>> value fields in a single int, they are read and written atomically as a
>> pair. Of course, were you to do this, you might want to avoid String's
>> ability to generate a code which looks like a flag indicating the lack
>> of a code (ie 0). But then, you might think the one in four billion
>> chance of it happening was insignificant.

Joshua Cranmer wrote:
> Or you could store the value in the low word of a long and the flag in
> the upper word.

But then you'd need to synchronize, unlike in 'String#hashCode()'.

--
Lew
From: Lew on
Tom Anderson wrote:
>> To make this method safe, you either have to synchronize the whole thing,
>> or do the update of calculated and code atomically at the end.

Andreas Leitgeb wrote:
> I'd have expected that if "calculated" was assigned *after* "code", that
> would suffice without further synchronisation or volatile-ity of the fields.
>
> Am I still too naive?

Yes. Don't omit what tom said about /happens-before/:
> In fact, it's worse than that. Thread A could finish the method and update both calculated and code, but because there is no happens-before relationship between thread A and thread B, it's possible that B could come along later, and see the updated calculated but *not* the updated code. So even without an unlucky timeslice end, there is no guarantee of safety here.

Thread B could obtain a value of '0' even chronologically after the entire
calculation, absent synchronization.

Tom Anderson wrote:
>> course, were you to do this, you might want to avoid String's ability to
>> generate a code which looks like a flag indicating the lack of a code (ie
>> 0). But then, you might think the one in four billion chance of it
>> happening was insignificant.

Andreas Leitgeb wrote:
> I guess, I'd have spent one "if (h==0) { h=42; }" just before "hash = h;"
> After the calculation loop, that extra "if" really wouldn't have hurt.

How is 42 any better than 0? And what, may I ask, is wrong with 0?

> Has anyone found e.g. an english [sic] dictionary-word with hashCode 0, yet?
> Or perhaps the name of some commonly used class in Java standard library
> or some other String likely occurring in innocent code?

""

--
Lew