On Tue, Sep 15, 2015 at 2:33 PM, Mark Thomas <ma...@apache.org> wrote:
> On 15/09/2015 21:51, Yilong Li wrote: > > On Tue, Sep 15, 2015 at 1:09 PM, Mark Thomas <ma...@apache.org> wrote: > > > >> On 15/09/2015 20:42, Caldarale, Charles R wrote: > >>>> From: Mark Thomas [mailto:ma...@apache.org] > >>>> Subject: Re: RV-Predict bugs > >>> > >>>> Putting it into my own words to check my understanding: > >>> > >>>> - The two reads in T2 may be re-ordered because, in T2, there is > nothing > >>>> that requires a happens-before relationship between the two reads > >>> > >>> Depends on what was really meant by the ??? notation. If it were > >> another reference to st_200, then the example ignores the potential > write > >> to st_200. > >>> > >>>> - If T2 was executing in isolation the order of the reads wouldn't > >>>> matter > >>> > >>> Correct, assuming there is no write in T2's control flow. > >>> > >>>> - However, T1 is writing. > >>> > >>>> So if the writes > >>> > >>> I'll assume you meant "reads" there. > >> > >> I'd did. Thanks. > >> > >>>> in T2 are re-ordered and the write from T1 takes place between them > the > >> T2 > >>>> read for the line 'st_200 == null' could return a non-null value for > >> st_200 > >>>> (the value after the write from T1) while the read for the line > 'return > >>>> st_200;' could return null (the value from before the write in T1). > >>> > >>> No - that would violate program order (intra-thread semantics). The > >> compiler cannot legally move the read for "return st_200" to a point > before > >> the potential write to st_200. The CPU can speculatively read for the > >> return value, but must discard such speculation if a write were to occur > >> (or use store forwarding to update the read). > >> > >> Thanks for sticking with me on this. I'm finding it hugely helpful. I > >> think I need a few more references to make things clearer so I'm going > >> to restate the problem. > >> > >> st_200 is non-volatile > >> > >> L1 if (st_200 == null ) { > >> L2 st_200 = sm.getString("sc.200"); > >> L3 } > >> L4 return st_200; > >> > >> Ln=Line n > >> Tx=Thread x > >> Rn=Read at line n > >> Wn=Write at line n > >> > >> So T2 has two reads, T2R1 and T2R4. > >> Depending on the value read for T2R1 there may be a write at T2W2. > >> If there is a write there is a happens before relationship between T2R1 > >> and T2R4. > >> > >> Consider the following sequence > >> > >> T2R4 (out of order read returns null) > >> T1R1 (returns null) > >> T1W2 (writes non-null value) > >> T1R4 (reads new non-null value) > >> T2R1 (reads new non-null value) > >> > >> Because T2R1 reads a non-null value there is no write in T2. > >> Therefore there is no happens-before relationship between T2R1 and T2R4 > >> because there is no intervening write in that thread (the write happens > >> in T1). > >> Therefore the re-ordering is allowed to happen. > >> And we get the unexpected result. > >> > >> Or > >> > >> The write at T1W2 is sufficient to enforce the happens before > >> relationship between T2R1 and T2R4. In which case what is the point of > >> volatile? What do I gain by using it? > >> > > > > Again, as I mentioned in my previous message, I am afraid this is not the > > correct way to use HB relationship. To make things more clear, I steal > this > > transformation from Jeremy Manson's article I sent before: > > That doesn't help my improve my understanding at all. > > What I'm looking for is an explanation - ideally using my example above > - of exactly how T2R4 can return null while T2R1 reads a non-null value. > "Because the JMM says it can" is not a sufficient explanation. I > believe that the JMM says it can but I don't understand how this can > actually happen. What I am looking for is the explanation of how. Your > message at 16.59 (UTC) was heading in the right direction but the > explanation skipped over the crucial part. > Fine. Let's do your example: T2R4 (out of order read returns null) T1R1 (returns null) T1W2 (writes non-null value) T1R4 (reads new non-null value) T2R1 (reads new non-null value) First of all, when reasoning with JMM, you should not move T2R4 to the front. This is forbidden by the intra-thread semantics so I move it back to the bottom: T1R1 (returns null) T1W2 (writes non-null value) T1R4 (reads new non-null value) T2R1 (reads new non-null value) T2R4 (out of order read returns null) Intra-thread semantics ensures the following HB order: T1R1 < T2W2 < T1R4 T2R1 < T2R4 T2R4 is allowed to read null because 1) T2R4 is not ordered before the write of null (let's call it INIT) by JVM during object initialization; and 2) there is no intervening write w' such that INIT < w' < T2R4. You see, T1W2 is *not* an intervening write because there is no HB order between T1W2 & T2R4. Let me know if it is still not clear enough. Yilong > Providing the explanation of how is the difference between: > a) a bug being theoretically valid based on the JMM but a practically > never going to happen because JVMs aren't written that way > vs. > b) a bug that can happen with current JVMs. > > We care a lot more about b) than we do a). And we may choose to not to > care at all about a). > > Assuming the answer is b) then there is potentially a wider benefit if a > clear explanation of the why can be provided since that is the sort of > thing that makes it a lot easier to convince people there is a real > problem they need to fix. > > Mark > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail: dev-h...@tomcat.apache.org > >