Linux的线程模型
自Linux诞生以来有三种
- LinuxThreads, 最早的模型, 只部分实现POSIX Threads标准
- NGPT, Next Generation POSIX Threads, 已终止
- NPTL, Native POSIX Thread Library, 从2.6内核以来到现在所使用的模型
在NPTL中, Linux使用的用户线程与内核线程1:1内应的线程模型, 这也是众多其它系统, win32, Solaris, NetBSD, FreeBSD, macOS, iOS等所采用的模型, 1:1模型的实现相对N:1和M:N要简单些.
当调用pthread库创建一个线程时, pthread_create
会调用clone
系统调用, 最终会创建一个LWP(轻量级进程)和一个内核线程. NPTL的1:1模型,即1个轻量级线程对应1个内核线程. 此时该LWP在内核态有对应的task_struct(进程描述符), 是一个独立的线程调度单元
Linux的进程与线程
对于系统而言并不区分进程与线程, 创建进程与创建线程都是使用fork
系统调用, 只是传参上的区别, 比如子进程会有自己的独立地址空间, 而线程则会共享空间. 内核进行调度的单位是task
.
可认为Linux里的线程本质上是共享资源的一系列进程.
LWP/用户线程/内核线程
LWP, Light-weight process, 即轻量级线程, 本质上来讲一种由内核支持的用户线程.
内核线程, 只访问内核空间, 共享相同的内核页表, 所有内核线程的内核空间是相同的, 而用户线程则是拥有自己的地址空间(与非同一进程的其它线程的空间不同).
用户线程, 标准意义上的用户线程应当是完全建立在用户空间的线程,用户线程的创建,同步,销毁,调度完全在用户空间完成,不需要内核的协助. 这个定义与LWP存在一定的交叉.
上下文切换
被抢占的LWP, 需要在用户态保存当前寄存器, 然后切换到内核态, 保存对应内核线程的寄存器, 恢复调度时, 分别恢复这两个现场, 涉及至少两次的栈切换和一定程度的缓存失效.
Green threads
绿色线程, 由运行时库或虚拟机进行调度的”线程”, 完全在用户空间进行管理.
Jdk1.2之前, 在Solaris等平台上实现的线程模型, 类型上属于绿色线程. 早期的Linux线程模型也属于绿色线程.
另外常见属于此类型的实现主要是协程, 像Java中的Quasar, Python中的Greenlet等.
Coroutine
协程, 是为解决非抢占式多任务处理的泛化子例程, 本质上是一种程序控制机制. 协程可以有多个入口点,可以在指定位置挂起和恢复执行.
协程分为两类
- 非对称式协程, 协程间有调用链关系, 有两种传递程序控制权的方式(resume/yield), 一个非对称协程可看做从属于它的调用者
- 对称式协程, 只有一种传递程序控制权的操作(coroutine.transfer)
Fiber
“纤程”, 基本上可认为是带调度器的有栈协程的实现
Java创建的线程是什么线程
Java 1.2以前有些是Green threads.
1.2以后, 以Linux平台为例, 线程的创建最终是调用到pthread_create
, 是内核级线程
细节在这里
参考