import java.util.ArrayList; import java.util.List; /** * Virtual threads and synchronized: until JEP 491 (Java 24) a virtual thread that blocked inside a synchronized * block kept its carrier thread (was "pinned"). With ONE carrier, four virtual threads that each sleep 200 ms inside * synchronized on their own lock take about 800 ms if pinned (one at a time) and about 200 ms if not (all at once). * Run by scripts/lanes.sh with -Djdk.virtualThreadScheduler.parallelism=1 -Djdk.virtualThreadScheduler.maxPoolSize=1 * Chapter: docs/14-lanes-21-to-25.md */ public class PinningDemo { public static void main(String[] args) throws Exception { System.out.println("java.version = " + System.getProperty("java.version")); List threads = new ArrayList<>(); long t0 = System.nanoTime(); for (int i = 0; i < 4; i++) { Object lock = new Object(); threads.add(Thread.ofVirtual().start(() -> { synchronized (lock) { try { Thread.sleep(200); } catch (InterruptedException ignored) { } } })); } for (Thread t : threads) t.join(); long ms = (System.nanoTime() - t0) / 1_000_000; System.out.println("4 virtual threads, 1 carrier, sleep(200) inside synchronized: " + (ms >= 700 ? "SERIALISED (pinned): about 4 x 200 ms" : "OVERLAPPED (not pinned): about 200 ms")); } }