<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div dir="ltr"></div><div dir="ltr">Only the thread calling get() (or any thread spawned after) is guaranteed to see the changes. Btw this code only works at all because you are using a single threaded executor or you’d have a concurrent modification exception </div><div dir="ltr"><br><blockquote type="cite">On Mar 21, 2024, at 5:03 AM, Arkadiusz Gasiński <jigga@jigga.pl> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr">Hi there,<div><br></div><div>I realize this mailing list is not intended for general concurrency-related discussions, however, I'll still give it a shot as there are a lot of concurrency experts subscribed to this list. </div><div><br></div><div>Please redirect me to a more suitable mailing list, if this message is unnecessary noise.</div><div><br></div><div>I had a discussion recently about a piece of code that's semantically equivalent to the code snippet below:</div><div><br></div><div><div style="color:rgb(0,0,0);font-family:"JetBrains Mono",Consolas,"Courier New",monospace,Consolas,"Courier New",monospace;font-size:14px;line-height:20px;white-space:pre"><div><span style="color:rgb(0,0,255)">public</span> <span style="color:rgb(0,0,255)">class</span> ListDemo {</div><div> <span style="color:rgb(0,0,255)">public</span> <span style="color:rgb(0,0,255)">static</span> <span style="color:rgb(0,0,255)">void</span> main(<span style="color:rgb(0,0,255)">String</span>[] args) <span style="color:rgb(0,0,255)">throws</span> <span style="color:rgb(0,0,255)">Exception</span> {</div><div> <span style="color:rgb(0,0,255)">final</span> <span style="color:rgb(0,0,255)">var</span> list = <span style="color:rgb(0,0,255)">new</span> <span style="color:rgb(0,0,255)">ArrayList</span><<span style="color:rgb(0,0,255)">Integer</span>>();</div><div> <span style="color:rgb(0,0,255)">try</span>(<span style="color:rgb(0,0,255)">var</span> executor = Executors.newSingleThreadExecutor()) {</div><div> <span style="color:rgb(0,0,255)">final</span> <span style="color:rgb(0,0,255)">var</span> futures = IntStream.iterate(<span style="color:rgb(9,134,88)">1</span>, i <span style="color:rgb(0,0,255)">-></span> ++i)</div><div> .limit(<span style="color:rgb(9,134,88)">1_000_000</span>)</div><div> .parallel() <span style="color:rgb(0,128,0)">// a little randomness</span></div><div> .mapToObj(i <span style="color:rgb(0,0,255)">-></span> (<span style="color:rgb(0,0,255)">Supplier</span><Integer>) () <span style="color:rgb(0,0,255)">-></span> {</div><div> list.add(i);</div><div> <span style="color:rgb(0,0,255)">return</span> i;</div><div> })</div><div> <span style="color:rgb(0,128,0)">// all tasks are supplied to the single-threaded executor</span></div><div> .map(supplier <span style="color:rgb(0,0,255)">-></span> CompletableFuture.supplyAsync(supplier, executor));</div><div> <span style="color:rgb(0,128,0)">// await completion</span></div><div> CompletableFuture.allOf(futures.toArray(<span style="color:rgb(0,0,255)">CompletableFuture</span>[]<span style="color:rgb(0,0,255)">::new</span>)).get();</div><div> <span style="color:rgb(0,128,0)">// use the list</span></div><div> System.out.println(list.size() == <span style="color:rgb(9,134,88)">1_000_000</span>);</div><div> }</div><div> }</div><div>}</div></div></div><div><br></div><div>My question is: will all changes (writes) made to the list declared at the start of the main method be visible in the main thread after the ComplietableFuture.allOf(...).<b>get</b>() call returns.</div><div><br></div><div>From <a href="https://docs.oracle.com/en%2Fjava%2Fjavase%2F21%2Fdocs%2Fapi%2F%2F/java.base/java/util/concurrent/Future.html">the Future</a> javadocs we have this one sentence:</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span style="color:rgb(71,71,71);font-family:"DejaVu Serif",Georgia,"Times New Roman",Times,serif;font-size:14px">Memory consistency effects: Actions taken by the asynchronous computation </span><a href="https://docs.oracle.com/en%2Fjava%2Fjavase%2F21%2Fdocs%2Fapi%2F%2F/java.base/java/util/concurrent/package-summary.html#MemoryVisibility" style="text-decoration-line:none;font-family:"DejaVu Serif",Georgia,"Times New Roman",Times,serif;font-size:14px"><i>happen-before</i></a><span style="color:rgb(71,71,71);font-family:"DejaVu Serif",Georgia,"Times New Roman",Times,serif;font-size:14px"> actions following the corresponding </span><code style="font-size:14px;padding-top:4px;margin-top:8px;line-height:1.4em;color:rgb(71,71,71)">Future.get()</code><span style="color:rgb(71,71,71);font-family:"DejaVu Serif",Georgia,"Times New Roman",Times,serif;font-size:14px"> in another thread.</span></blockquote><div><br></div><div>And due to that, my understanding is that all writes to the list happen before the subsequent (after get returns) reads from the list, and no matter what thread reads the list, it will ALWAYS observe all changes made to the list.</div><div><br></div><div>Is my understanding correct? If not, please let me know.</div><div><br></div><div>Thanks,</div><div>Arek </div></div>
</div></blockquote></body></html>