<div dir="ltr"><div>When the virtual thread hits the read(), it blocks.  The virtual thread's call stack is copied off the carrier thread's stack.  When the virtual thread unblocks, another carrier thread copies the virtual thread's call stack back to the carrier thread's stack. Both of these operations require synchronization (or happens before) to ensure the virtual thread's stack is safely passed from one carrier thread to another carrier thread.  This synchronization ensures the passing of "this" from one carrier thread to another carrier thread is safe.  Hence, the unsafe() method is safe with regards to a virtual thread executing on several different carrier threads.</div><div><br></div><div>unsafe() is not safe from multiple virtual threads calling it on the same "this".  unsafe() is not safe from multiple OS threads calling it on the same "this".<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Nov 22, 2023 at 11:44 AM Mark Raynsford <<a href="mailto:org.openjdk@io7m.com">org.openjdk@io7m.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Wed, 2023-11-22 at 10:24 -0800, Nathan Reynolds wrote:<br>
> <br>
> I haven't played with Loom threads yet.  From what I have read, it<br>
> doesn't<br>
> sound like Loom threads change the functional behavior of the<br>
> program.<br>
> Loom threads only change the performance behavior.<br>
<br>
They actually do. I was surprised by (and bitten by this):<br>
<br>
  private final Map<String, String> data;<br>
<br>
  void unsafe()<br>
  {<br>
    this.data.put("x", "y");<br>
    System.in.read();<br>
    this.data.put("x", "z");<br>
  } <br>
<br>
The above unsafe() method is safe when called on a single platform<br>
thread. This is just normal "thread confinement" of the kind we've<br>
been using for years. The unsafe() method isn't safe when called by<br>
a single virtual thread. Why? Because the call to System.in.read()<br>
will cause the virtual thread to yield, and it may be resumed on<br>
a different _carrier_ thread after the read() call finishes. Nothing<br>
ensures those calls to Map.put() will result in safe publication.<br>
<br>
It just means that code that was safe to call on a single platform<br>
thread that assumed thread confinement (and so didn't synchronize its<br>
own private data) will break in perhaps surprising ways when called on<br>
a single virtual thread.<br>
<br>
-- <br>
Mark Raynsford | <a href="https://www.io7m.com" rel="noreferrer" target="_blank">https://www.io7m.com</a><br>
<br>
</blockquote></div>