跳到主要内容

进程与线程

问题

进程和线程有什么区别?Java 线程和操作系统线程的关系?

答案

进程 vs 线程

维度进程线程
定义资源分配的基本单位CPU 调度的基本单位
资源独立的内存空间共享进程的内存
开销创建/切换开销大创建/切换开销小
通信IPC(管道、Socket 等)共享内存,直接通信
影响进程崩溃不影响其他进程线程崩溃导致整个进程崩溃
数量一般较少一个进程可有多个线程

线程的状态(操作系统层面)

Java 线程与操作系统线程

Java 线程(HotSpot JVM)是 1:1 映射到操作系统内核线程的。new Thread().start() 最终调用操作系统的 pthread_create()

Java 21 虚拟线程

Java 21 引入虚拟线程(Virtual Thread),是 M:N 模型——M 个虚拟线程映射到 N 个平台线程。虚拟线程非常轻量(几 KB),可以创建百万级。

// 虚拟线程
Thread.startVirtualThread(() -> {
// 阻塞操作不会占用平台线程
Thread.sleep(1000);
});

详见 Java 新特性

上下文切换

线程切换时需要保存/恢复 CPU 寄存器、程序计数器、栈指针等状态,这就是上下文切换。切换代价:

  • 直接成本:寄存器保存/恢复、内核态切换
  • 间接成本:CPU 缓存失效(Cache Miss)

查看 Linux 系统上下文切换次数:vmstat 1cs 列。


常见面试问题

Q1: 什么是协程?Java 支持吗?

答案

协程是用户态的轻量级线程,调度由用户程序控制,不需要内核参与。

  • Go 语言的 goroutine、Kotlin 的 coroutine 都是协程
  • Java 21 的虚拟线程(Virtual Thread)本质就是协程实现

协程优势:创建开销极小、无内核态切换、适合高并发 IO 场景。

Q2: 为什么进程切换比线程切换慢?

答案

进程切换除了保存/恢复线程上下文外,还需要:

  1. 切换页表(虚拟内存映射)
  2. 刷新 TLB 缓存(地址翻译缓存)
  3. 可能导致更严重的 CPU Cache Miss

线程切换只需保存/恢复少量寄存器,因为同进程的线程共享内存空间。

Q3: 多线程一定比单线程快吗?

答案

不一定。以下场景单线程可能更快:

  1. CPU 密集型 + 单核:线程切换是纯开销
  2. 任务很轻:线程创建/切换的开销大于任务本身
  3. 大量锁竞争:线程频繁阻塞等待

Redis 就是单线程模型(6.0 前),因为瓶颈在网络 IO 而不是 CPU。

相关链接