<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
Hi.
<div class=""><br class="">
</div>
<div class="">What you’re seeing is the result of the virtual thread scheduler not employing time sharing. That is because we have yet to identify workloads, especially those that are best served by virtual threads — namely, servers — that can benefit from
it. Once we find such workloads we’ll be able to utilise time sharing.</div>
<div class=""><br class="">
</div>
<div class="">In your example, the scheduler is able to keep all threads busy with work without blocking on the semaphore by just running some threads.</div>
<div class=""><br class="">
</div>
<div class="">— Ron<br class="">
<div><br class="">
<blockquote type="cite" class="">
<div class="">On 16 Apr 2023, at 06:30, Martin Traverso <<a href="mailto:mtraverso@gmail.com" class="">mtraverso@gmail.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">Hi,<br class="">
<br class="">
First of all, I'd like to thank you for this feature! We've been eagerly awaiting it in the Trino project and we believe it will help us dramatically simplify many parts of the codebase.<br class="">
<br class="">
I've been playing around with virtual threads and I've noticed some odd behaviors. Given the following code:<br class="">
<br class="">
<font face="monospace" class=""> import java.util.ArrayList;<br class="">
import java.util.List;<br class="">
import java.util.concurrent.ExecutionException;<br class="">
import java.util.concurrent.Semaphore;<br class="">
import java.util.concurrent.atomic.AtomicLong;<br class="">
<br class="">
public class Test<br class="">
{<br class="">
public static void main(String[] args)<br class="">
throws InterruptedException<br class="">
{<br class="">
int processors = Runtime.getRuntime().availableProcessors();<br class="">
<br class="">
Semaphore semaphore = new Semaphore(processors, true);<br class="">
List<AtomicLong> counters = new ArrayList<>();<br class="">
for (int i = 0; i < 2 * processors; i++) {<br class="">
AtomicLong counter = new AtomicLong();<br class="">
counters.add(counter);<br class="">
Thread.ofVirtual().start(() -> {<br class="">
while (true) {<br class="">
semaphore.acquireUninterruptibly();<br class="">
counter.incrementAndGet();<br class="">
semaphore.release();<br class="">
}<br class="">
});<br class="">
}<br class="">
<br class="">
Thread.sleep(10_000);<br class="">
<br class="">
counters.stream()<br class="">
.map(AtomicLong::get)<br class="">
.sorted()<br class="">
.forEach(System.out::println);<br class="">
}<br class="">
}</font><br class="">
<br class="">
I would expect the counts to be approximately equal, but I'm getting the following result:<br class="">
<br class="">
0<br class="">
0<br class="">
0<br class="">
0<br class="">
0<br class="">
0<br class="">
0<br class="">
0<br class="">
0<br class="">
0<br class="">
2435341<br class="">
2448274<br class="">
2466202<br class="">
2497258<br class="">
2539030<br class="">
2572744<br class="">
2592871<br class="">
2611658<br class="">
2651392<br class="">
2657913<br class="">
<br class="">
If I change the number of permits for the semaphore to a value smaller than the number of processors, then the results come out as expected. It also works as expected if I change the core loop to make a call to Thread.yield() on the first iteration:<br class="">
<br class="">
<font face="monospace" class=""> while (true) {<br class="">
semaphore.acquireUninterruptibly();<br class="">
if (counter.incrementAndGet() == 1) {<br class="">
Thread.yield();<br class="">
}<br class="">
semaphore.release();<br class="">
}<br class="">
</font><br class="">
<br class="">
If I place a call to Thread.yield() after the semaphore.release() call, then all the threads make some progress, but the values are still unbalanced:<br class="">
<br class="">
<font face="monospace" class=""> while (true) {<br class="">
semaphore.acquireUninterruptibly();<br class="">
counter.incrementAndGet();<br class="">
semaphore.release();<br class="">
Thread.yield();<br class="">
}</font><br class="">
<br class="">
196257<br class="">
196257<br class="">
196258<br class="">
196260<br class="">
196260<br class="">
196260<br class="">
196261<br class="">
196261<br class="">
401737<br class="">
401740<br class="">
401744<br class="">
401757<br class="">
1644985<br class="">
1651301<br class="">
1677466<br class="">
1683009<br class="">
1694577<br class="">
1702710<br class="">
1710970<br class="">
1843037<br class="">
<br class="">
I'm running the following version of the JDK on an Macbook Pro with an M1 Max CPU:<br class="">
<br class="">
openjdk version "20" 2023-03-21<br class="">
OpenJDK Runtime Environment Zulu20.28+85-CA (build 20+36)<br class="">
OpenJDK 64-Bit Server VM Zulu20.28+85-CA (build 20+36, mixed mode, sharing)<br class="">
<br class="">
I'm not sure if this is a bug or if I'm misunderstanding how virtual threads are supposed to work. Any help or clarification would be greatly appreciated!<br class="">
<br class="">
Thanks!<br class="">
- Martin<br class="">
<div class="">
<div dir="ltr" data-smartmail="gmail_signature" class="">
<div dir="ltr" class="">
<div class="">
<div class=""><br class="">
</div>
<div class="">----</div>
</div>
<div class="">
<div class="">Martin Traverso</div>
<div class="">Co-founder @ Trino Software Foundation, Co-creator of Presto and Trino (<a href="https://trino.io/" target="_blank" class="">https://trino.io</a>)</div>
</div>
<div class=""><br class="">
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
<br class="">
</div>
</body>
</html>