Prev: Immediate Start: Need Designer's (Visual/Graphic),Beverly Hills,California,
Next: a question about alias of reference
From: Lew on 18 Jul 2010 17:32 Lew wrote: >> 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. Andreas Leitgeb wrote: > There is still a misunderstanding - I'm just not sure if it's on my or your > side. > Thread 1 assigns two plain word-sized fields: a and then b. > can Thread 2 happen to see b's new value, and (after that) a's old value? Yes. > Tom's explanation was (as far as I understood it) based on the code-sample > where the flag was set before the code, and he rightly pointed out that this > gap may be even much longer than expected. Can it reverse, as well? Yes. When thread A changes values for shared data 'a' and 'b' without establishment of /happens-before/, at some later time (even chronologically after both values were changed), a different thread B can examine those data and find any of four states: the old value for both 'a' and 'b', the old value for 'a' and new for 'b', the new value for 'a' and old for 'b', or the new value for both. You'll need multiple cores to encounter these scenarios, most likely, and it will depend on whether they use a NUMA, various caching strategies, how far apart in the memory architecture the cores are, the load at the time, ... Andreas Leitgeb wrote: >>> 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 wrote: >> "" Andreas Leitgeb wrote: > Damn, I shouldn't have trimmed the "non-trivial" that I had already written. > At least, the hashCode for "" is quite efficiently obtained. It's not really trivial. "" is an extremely common 'String' value and frequently can be the key to a hashed structure, so its hash value is relevant. -- Lew
From: Patricia Shanahan on 18 Jul 2010 17:55 Andreas Leitgeb wrote: > Lew <noone(a)lewscanon.com> wrote: >> 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. > > There is still a misunderstanding - I'm just not sure if it's on my or your > side. > Thread 1 assigns two plain word-sized fields: a and then b. > can Thread 2 happen to see b's new value, and (after that) a's old value? > > Tom's explanation was (as far as I understood it) based on the code-sample > where the flag was set before the code, and he rightly pointed out that this > gap may be even much longer than expected. Can it reverse, as well? Depends on the memory order rules in the hardware. I'm most familiar with the rules for SPARC v9, but other processors have their own rules. In Total Store Order they cannot reverse. In Relaxed Memory Order and Partial Store Order, they can reverse, from the point of view of other processors, unless some action such as a membar #StoreStore forces ordering. See http://en.wikipedia.org/wiki/Memory_ordering#In_SMP_microprocessor_systems Patricia
From: Andreas Leitgeb on 18 Jul 2010 18:06 Lew <noone(a)lewscanon.com> wrote: > Andreas Leitgeb wrote: >> Thread 1 assigns two plain word-sized fields: a and then b. >> can Thread 2 happen to see b's new value, and (after that) a's old value? > Yes. >> Tom's explanation was (as far as I understood it) based on the code-sample >> where the flag was set before the code, and he rightly pointed out that this >> gap may be even much longer than expected. Can it reverse, as well? > Yes. > When thread A changes values for shared data 'a' and 'b' without establishment > of /happens-before/, at some later time (even chronologically after both > values were changed), a different thread B can examine those data and find any > of four states: the old value for both 'a' and 'b', the old value for 'a' and > new for 'b', the new value for 'a' and old for 'b', or the new value for both. Thanks for ultimate clarification! > Andreas Leitgeb wrote: >>>> 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 wrote: >>> "" > Andreas Leitgeb wrote: >> Damn, I shouldn't have trimmed the "non-trivial" that I had already written. >> At least, the hashCode for "" is quite efficiently obtained. > It's not really trivial. "" is an extremely common 'String' value and > frequently can be the key to a hashed structure, so its hash value is relevant. The empty String *is* trivial, and triviality doesn't imply uncommonness or irrelevance. The hashcode of "" doesn't take long to compute, but if e.g. a String like "java.lang.String" had an hashCode of 0, then the necessity to recalc it each time might be more noticeable/relevant than for "".
From: Andreas Leitgeb on 18 Jul 2010 18:22 Patricia Shanahan <pats(a)acm.org> wrote: > Andreas Leitgeb wrote: >> Thread 1 assigns two plain word-sized fields: a and then b. >> can Thread 2 happen to see b's new value, and (after that) a's old value? > Depends on the memory order rules in the hardware. I'm most familiar > with the rules for SPARC v9, but other processors have their own rules. > In Total Store Order they cannot reverse. In Relaxed Memory Order and > Partial Store Order, they can reverse, from the point of view of other > processors, unless some action such as a membar #StoreStore forces ordering. > See > http://en.wikipedia.org/wiki/Memory_ordering#In_SMP_microprocessor_systems Thanks for the processor-specific infos. It means, that an attempt to "produce" such a reversion (in the sense as one can "produce" a deadlock) may be doomed if on the "wrong" platform.
From: Peter Duniho on 18 Jul 2010 18:39
Andreas Leitgeb wrote: > Patricia Shanahan <pats(a)acm.org> wrote: >> Andreas Leitgeb wrote: >>> Thread 1 assigns two plain word-sized fields: a and then b. >>> can Thread 2 happen to see b's new value, and (after that) a's old value? >> Depends on the memory order rules in the hardware. I'm most familiar >> with the rules for SPARC v9, but other processors have their own rules. >> In Total Store Order they cannot reverse. In Relaxed Memory Order and >> Partial Store Order, they can reverse, from the point of view of other >> processors, unless some action such as a membar #StoreStore forces ordering. >> See >> http://en.wikipedia.org/wiki/Memory_ordering#In_SMP_microprocessor_systems > > Thanks for the processor-specific infos. > It means, that an attempt to "produce" such a reversion (in the sense as > one can "produce" a deadlock) may be doomed if on the "wrong" platform. Keep in mind that it's not just hardware implementation that affects this. Compiler optimizations can change the order of reads and writes as well. The bottom line is that if the order of reads and writes is important, there needs to be some kind of synchronization in the code to accomplish that. It may be sufficient to specify "volatile", or a more costly synchronization technique may be needed (such as acquiring the monitor for an object). This is true even if running the code on a single-core CPU. Presumably, the choice of the existing hashCode() implementation for String was made based on the assumption that the overhead of even "volatile" was more important to avoid than the remote possibility that multiple threads may wind up calculating the hash code for the same string instance. And, also presumably, this is the same thinking that led to the code in which those unfortunate strings with a hash code of 0 always wind up getting recalculated no matter what (because otherwise, one would need a flag, separate from the hash code field, which could wind up out-of-sync with the hash code field absent synchronization, such as "volatile"�as discussed previously in this thread). Pete |