<story><title>JEP proposed to target JDK 19: 425: Virtual Threads (Preview)</title><url>https://mail.openjdk.java.net/pipermail/jdk-dev/2022-April/006530.html</url></story><parent_chain><item><author>pron</author><text>&amp;gt; I wonder why we went down that whole async&amp;#x2F;await craze with so many languages?&lt;p&gt;We addressed this, albeit very briefly, in the Alternatives section of the JEP: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;openjdk.java.net&amp;#x2F;jeps&amp;#x2F;425&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;openjdk.java.net&amp;#x2F;jeps&amp;#x2F;425&lt;/a&gt;&lt;p&gt;There are multiple reasons:&lt;p&gt;1. Languages that don&amp;#x27;t already have threads have an implicit assumption built into all existing code that program state cannot change concurrently. This is why scheduling points need to be marked explicitly, and why adding threads — whether user-mode or OS — might break existing code in some very tricky ways. That&amp;#x27;s the case of JavaScript.&lt;p&gt;2. Some languages target an IR without control over its backend, making an efficient implementation of user-mode threads difficult, if not impossible. async&amp;#x2F;await requires only changes to the frontend compiler. That&amp;#x27;s the case of Kotlin, and, perhaps to a lesser extent, Rust.&lt;p&gt;3. Some languages have technical features that make implementing user-mode threads efficiently more difficult than in others. Pointers into the stack and careful control over memory allocation make this more challenging in languages like C++ and Rust than in Java.</text></item><item><author>nu11ptr</author><text>From &lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;cr.openjdk.java.net&amp;#x2F;~rpressler&amp;#x2F;loom&amp;#x2F;loom&amp;#x2F;sol1_part1.html&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;cr.openjdk.java.net&amp;#x2F;~rpressler&amp;#x2F;loom&amp;#x2F;loom&amp;#x2F;sol1_part1.h...&lt;/a&gt;:&lt;p&gt;&amp;quot;Whereas the OS can support up to a few thousand active threads, the Java runtime can support millions of virtual threads. Every unit of concurrency in the application domain can be represented by its own thread, making programming concurrent applications easier. Forget about thread-pools, just spawn a new thread, one per task. You’ve already spawned a new virtual thread to handle an incoming HTTP request, but now, in the course of handling the request, you want to simultaneously query a database and issue outgoing requests to three other services? No problem — spawn more threads. You need to wait for something to happen without wasting precious resources? Forget about callbacks or reactive stream chaining — just block. Write straightforward, boring code. All the benefits threads give us — control flow, exception context, debugging flow, profiling organization — are preserved by virtual threads; only the runtime cost in footprint and performance is gone. There is no loss in flexibility compared to asynchronous programming because, as we’ll see, we have not ceded fine-grained control over scheduling.&amp;quot;&lt;p&gt;This seems so obvious in hindsight as the &amp;quot;right way&amp;quot;. I wonder why we went down that whole async&amp;#x2F;await craze with so many languages?</text></item></parent_chain><comment><author>signal11</author><text>Ron, thank you for your work on Loom, it’s very exciting and I’m looking forward to using it in production code!&lt;p&gt;As an aside, Ron had a JUG talk 6 months ago which I found really helpful where he went into more detail about why they chose this approach: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;youtu.be&amp;#x2F;KmMU5Y_r0Uk&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;youtu.be&amp;#x2F;KmMU5Y_r0Uk&lt;/a&gt; (27m20s mark, and from 2m50 there’s a more general introduction to Loom).&lt;p&gt;I’m sure there are other videos&amp;#x2F;papers as well, but this was a pretty good overview of Java vs other languages’ approach to async.</text></comment>
<story><title>JEP proposed to target JDK 19: 425: Virtual Threads (Preview)</title><url>https://mail.openjdk.java.net/pipermail/jdk-dev/2022-April/006530.html</url></story><parent_chain><item><author>pron</author><text>&amp;gt; I wonder why we went down that whole async&amp;#x2F;await craze with so many languages?&lt;p&gt;We addressed this, albeit very briefly, in the Alternatives section of the JEP: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;openjdk.java.net&amp;#x2F;jeps&amp;#x2F;425&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;openjdk.java.net&amp;#x2F;jeps&amp;#x2F;425&lt;/a&gt;&lt;p&gt;There are multiple reasons:&lt;p&gt;1. Languages that don&amp;#x27;t already have threads have an implicit assumption built into all existing code that program state cannot change concurrently. This is why scheduling points need to be marked explicitly, and why adding threads — whether user-mode or OS — might break existing code in some very tricky ways. That&amp;#x27;s the case of JavaScript.&lt;p&gt;2. Some languages target an IR without control over its backend, making an efficient implementation of user-mode threads difficult, if not impossible. async&amp;#x2F;await requires only changes to the frontend compiler. That&amp;#x27;s the case of Kotlin, and, perhaps to a lesser extent, Rust.&lt;p&gt;3. Some languages have technical features that make implementing user-mode threads efficiently more difficult than in others. Pointers into the stack and careful control over memory allocation make this more challenging in languages like C++ and Rust than in Java.</text></item><item><author>nu11ptr</author><text>From &lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;cr.openjdk.java.net&amp;#x2F;~rpressler&amp;#x2F;loom&amp;#x2F;loom&amp;#x2F;sol1_part1.html&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;cr.openjdk.java.net&amp;#x2F;~rpressler&amp;#x2F;loom&amp;#x2F;loom&amp;#x2F;sol1_part1.h...&lt;/a&gt;:&lt;p&gt;&amp;quot;Whereas the OS can support up to a few thousand active threads, the Java runtime can support millions of virtual threads. Every unit of concurrency in the application domain can be represented by its own thread, making programming concurrent applications easier. Forget about thread-pools, just spawn a new thread, one per task. You’ve already spawned a new virtual thread to handle an incoming HTTP request, but now, in the course of handling the request, you want to simultaneously query a database and issue outgoing requests to three other services? No problem — spawn more threads. You need to wait for something to happen without wasting precious resources? Forget about callbacks or reactive stream chaining — just block. Write straightforward, boring code. All the benefits threads give us — control flow, exception context, debugging flow, profiling organization — are preserved by virtual threads; only the runtime cost in footprint and performance is gone. There is no loss in flexibility compared to asynchronous programming because, as we’ll see, we have not ceded fine-grained control over scheduling.&amp;quot;&lt;p&gt;This seems so obvious in hindsight as the &amp;quot;right way&amp;quot;. I wonder why we went down that whole async&amp;#x2F;await craze with so many languages?</text></item></parent_chain><comment><author>kevincox</author><text>I think you are missing a key benefit of async&amp;#x2F;await. It can be implemented incredibly efficiently. This is because it is &amp;quot;stackless&amp;quot;. Or in other words you know the exact amount of &amp;quot;stack&amp;quot; space required and you can allocate this exactly instead of allocating a real stack which can be very much larger.&lt;p&gt;For example if I want to implement a &amp;quot;sleep&amp;quot; with async&amp;#x2F;await I probably only need to store the wake time as state, if I want to make a virtual thread to do the same I likely need to allocate a large stack just in case I use it.&lt;p&gt;Of course this can be mitigated with stack caching, small stacks, segmented stacks or other tricks. But doing this is still more expensive than knowing how much &amp;quot;stack&amp;quot; you need up-front and allocating only that.</text></comment>