<div dir="ltr"><div><div>Thank you for the clarification. In this case, read actions in T2 are not ordered by happens-before order (HB) with the write actions in T1. And all these actions act on the same shared variables (fields of the list L). So by definition, you have a data race. And there is no guarantee that you will correctly read all the buffers that T1 added to the L.</div><div><br></div><div>I want to add, that generally there is no guarantee that you will see a non-null when reading L field from T2. However is your case this field is final, and the semantics of a final field guarantees HB* between a write to the field L (T1 writes there a reference to a new ArrayList()) and a read of the reference from L field in T2. Unfortunately, this HB* is not transitive with the normal HB, hence you don't have guarantees you initially asked about.</div></div><div><br></div><div>And one more thing: if you had started T2 from T1 after (in program order (PO)) T1 added all buffers to L, then you would have had HB between all actions in T1 (which are ordered in PO before the start of T2) and all actions in T2. But as far as I understand, your case is different and T2 is started not from T1.</div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><div style="margin:0px;padding:0px 0px 3px;color:rgb(0,0,0);font-family:Tahoma,Arial,Helvetica,sans-serif;font-size:14px"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px">Regards,</span><br></div></div><div style="margin:0px;padding:0px 0px 3px;color:rgb(0,0,0);font-family:Tahoma,Arial,Helvetica,sans-serif;font-size:14px"><span style="font-family:arial,sans-serif;font-size:12.8px;color:rgb(34,34,34)">Valentin</span></div><div style="margin:0px;padding:0px 0px 3px;color:rgb(0,0,0);font-family:Tahoma,Arial,Helvetica,sans-serif;font-size:14px"><span style="font-size:12.8px;font-family:arial,sans-serif;color:rgb(34,34,34)"></span></div><div><div style="color:rgb(102,102,102);font-family:"Open Sans",sans-serif;font-size:16px"></div></div></div></div></div></div></div></div></div></div></div>
<br><div class="gmail_quote">On 6 January 2018 at 20:07, Andriy Bukatar <span dir="ltr"><<a href="mailto:buka1974@yahoo.com" target="_blank">buka1974@yahoo.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">Thanks Valentin.<div>Yes, the devil is in the details.</div><div><br></div><div>I could rephrase the question as follows:</div><div><br></div><div>There’s a class C containing the non-concurrent list L.</div><div><br></div><div>Thread T1 adds a few items to the list L. </div><div><br></div><div>Thread T2 starts (note it did not exist at the time when T1 was updating the list L). Thread T2 gets a reference to C and iterates over its list L.</div><div><br></div><div>So “AFTER” in this case is a “wall clock distance” between the time T1 performs the last update to L and the time when T2 starts. </div><div><br></div><div>I know the answer to this question when T2 starts iterating over L before (or at the time when) T1 performs updates to non-concurrent L - no visibility guarantees whatsoever. </div><div><br></div><div>The question I suppose is whether non-existence of T2 at the time of the last update to L has any impact on visibility of the contents of L.</div><div><br></div><div>Not sure if this makes it any clearer and my apologies if it does not.</div><div><br></div><div>Thank you</div></div></blockquote></div></div></div>