The Virtual Thread Model: M:N Mapping in Java

Project Loom introduces Virtual Threads to the Java platform, fundamentally shifting how we handle concurrency. Unlike traditional Platform Threads, which are 1:1 wrappers around OS threads, Virtual Threads are user-mode threads managed by the JVM.

Key Concept: Virtual threads decouple the "thread" abstraction from the heavy operating system process scheduler. This allows creating millions of concurrent tasks without exhausting system resources.

The M:N Scheduling Model

Java implements virtual threads using an M:N model:

When a virtual thread runs code, it is "mounted" onto a carrier thread. When it performs a blocking I/O operation (like reading from a socket), the JVM "unmounts" it, freeing the carrier thread to execute another virtual thread. This non-blocking behavior is transparent to the developer.

Visualization: Carrier Scheduler

Carrier Scheduler Visualization (ForkJoinPool)

Ready Virtual Threads

VT #105
VT #106
VT #107
→ Mount →

Carrier Threads (OS)

Carrier-0
Running: VT #101
Carrier-1
Running: VT #104
Status: Carrier threads execute Virtual Threads from the shared work-stealing queue. When a VT blocks, it is unmounted, and the Carrier picks the next ready VT.

Why This Matters

This model solves the "Thread-per-Request" scalability bottleneck. In traditional server applications, the number of concurrent requests is limited by the number of OS threads (typically a few thousand). With virtual threads, the limit becomes available heap memory, allowing for significantly higher throughput for I/O-bound workloads.