24 聊聊虚拟线程

vvEcho 2026-02-26 16:16:18
Categories: Tags:

概念

JDK21提供了与 Thread 完全一致的抽象 Virtual Thread 来应对这种经常阻塞的情况,阻塞仍然是会阻塞,但是换了阻塞的对象,由昂贵的平台线程阻塞改为了成本很低的虚拟线程的阻塞,当代码调用到阻塞API例如IO,同步,Sleep 等操作时,JVM 会自动把虚拟线程从平台线程上卸载,平台线程就会去处理下一个虚拟线程,通过这种方式,提升了平台线程的利用率,让平台线程不再阻塞在等待上,从底层实现了少量平台线程就可以处理大量请求,提高了服务吞吐和CPU的利用率

虚拟线程的原理

虚拟线程本质是将线程的调度转为JVM用户态来做,之前线程的调度由操作系统线程(OS Thread)来完成,1个线程就对应一个操作系统的线程
;而每个线程都有自己的栈,而且线程的切换成本非常高;用户态切换到内核态,要先保存到CPU寄存器,然后切换后还有恢复上下文;而虚拟线程是MN的模型,一个操作系统线程可以对应挂载多个虚拟线程,当某个虚拟线程阻塞时,操作系统会将其卸载,然后对应的虚拟线程会被挂起,接着去调度其他的虚拟线程,等阻塞结束恢复对应的虚拟线程继续执行

为什么synchronized会导致Thread Pinning

synchronized 的锁是基于操作系统线程(OS Thread)实现的,而不是虚拟线程

为什么ReentrantLock不会导致Thread Pinning

1
2
3
4
5
6
7
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
Thread.sleep(1000);
} finally {
lock.unlock();
}

ReentrantLock 基于:AQS(AbstractQueuedSynchronizer),而AQS是基于jvm的park,unpark;是jvm可以控制的阻塞点
当虚拟线程执行:LockSupport.park(),JVM 会识别:当前线程是 Virtual Thread
于是做下面操作:
1 保存虚拟线程执行栈
2 卸载虚拟线程
3 释放 Carrier Thread

虚拟线程适合的场景

虚拟线程适用于 IO 密集型高并发场景,例如 Web 服务、RPC 调用、数据库访问、消息消费等。因为这些场景线程大部分时间处于阻塞状态,虚拟线程可以在阻塞时卸载释放 OS 线程,从而支持百万级并发。而 CPU 密集型任务不适合虚拟线程,因为 CPU 核心数是瓶颈

得物技术-虚拟线程