1 用户级线程
完全在用户空间中实现和管理的线程。
它们的创建、同步和调度由应用程序通过用户级别的线程库实现,所有的线程管理工作都由应用程序负责,无需操作系统内核干预。在用户看来有多个线程,但操作系统并不能意识到线程的存在。
缺点:它们不能充分利用多核处理器的并行能力。因为操作系统调度的基本单位是内核线程,当一个用户线程阻塞时(如I/O操作),整个进程都会被阻塞,即使其他用户线程仍处于就绪状态。这可能导致多处理器系统中的性能下降。
2 内核级线程
由操作系统内核直接支持和管理的线程。
内核负责创建、调度和销毁内核线程,每个内核线程都拥有独立的内核栈和线程上下文。一个线程被阻塞后,别的线程还可以继续执行,并发能力强,多线程可以在多核处理机上并行执行。
缺点:它们的创建、切换和同步操作涉及系统调用,线程管理的成本高,开销大。此外,内核线程需要更多的内核资源(如内核栈),这可能在大量线程的情况下导致资源耗尽。
3 多线程模型
用户线程和内核线程分别代表了两种线程实现方式。
- 用户线程的开销较小,但在多处理器系统中可能无法充分利用并行能力。
- 内核线程可以充分利用多处理器的并行能力,但开销较大。
在实际应用中,可以根据具体需求和性能要求选择合适的线程类型。
- 一对一模型:一个用户级线程映射到一个内核级线程
- 多对一模型:多个用户级线程映射到一个内核级线程
- 多对多模型:折中,克服了多对一模型并发度不高的缺点和一对一模型占用太多内核级线程、开销太大的缺点
4 Java线程和操作系统的线程有什么区别?
4.1 Green Threads
JDK 1.2 之前,Java 线程是基于Green Threads实现的,这是一种用户级线程。它们的创建、同步和调度由应用程序通过用户级别的线程库实现,所有的线程管理工作都由应用程序负责,无需操作系统内核干预。
用户线程的创建与切换开销较小,但它们不能充分利用多核处理器的并行能力。因为操作系统调度的基本单位是内核线程,当一个用户线程阻塞时(如I/O操作),整个进程都会被阻塞,即使其他用户线程仍处于就绪状态。这可能导致多处理器系统中的性能下降。
4.2 Native Threads
在 JDK 1.2 及以后,Java 线程改为基于原生线程实现,也就是说 JVM 直接使用内核线程来实现 Java 线程,由操作系统内核进行线程的调度和管理。
一个线程被阻塞后,别的线程还可以继续执行,并发能力强,多线程可以在多核处理机上并行执行。但它们的创建、切换和同步操作涉及系统调用,线程管理的成本高,开销大,可能需要更多的内核资源。
4.3 Java20新特性:Virtual Thread
是 JDK 而不是 OS 实现的轻量级线程(Lightweight Process,LWP),由 JVM 调度。许多虚拟线程共享同一个操作系统线程,虚拟线程的数量可以远大于操作系统线程的数量。
虚拟线程在其他多线程语言中已经被证实是十分有用的,比如 Go 中的 Goroutine。