操作系统中的多线程
概述
cpu 运行速度特别快,但是IO等资源比较慢,cpu多数时间都在等待,为了提高cpu 的利用率。提出了进程的概念。当一个进程阻塞后,切换到另一个进程来提高cpu的利用率。操作系统就是通过进程来管理cpu的。
进程
程序是静态的,进程是描述程序动态的程序。存放运行中的状态。cpu跑多个进程的状态,就是cpu 管理。
多进程如何组织
PCB+状态+队列
PCB
PCB:就是这个进程在操作系统中的“身份证”和“个人档案”。通常包含如下信息:
- 进程标识信息(我是谁?)
- 处理机状态信息(我现在的状态是什么?)
- 进程调度信息(我排在哪?优先级多高?)
- 进程控制信息(我有什么资源?)
进程状态

队列
上述每一个线程状态对应一种队列,这种状态的线程都在该队列里。
多进程如何交替
调度器从“就绪队列”里挑出一个进程,把它的 PCB 里的寄存器数据恢复到 CPU 中,让它开始运行。那么就绪队列中有很多就绪的进程,如何确定取哪一个进程,这就涉及到了调度算法。
调度算法
在就绪队列中有多个进程,应该选取哪一个。系统中的任务 大体分为两类 一类是CPU密集型任务,另一类是IO密集型任务。因此算法既要照顾cpu密集型任务也要照顾IO密集型任务。不能让一个任务一直运行,其他任务一直等待。最好是在调用cpu密集型任务时,把IO密集型任务调度起来。下面是一些常见的算法:
FCFS
先进先出
- 原理:就像排队买票一样,谁先提交任务,谁就先获得 CPU 资源。
- 特点:算法极其简单、公平。但它的致命缺点是对短作业不友好。如果前面来了一个执行时间很长的任务,后面一堆只需几毫秒的短任务就只能干等(这被称为“护航效应”)。
SJF 短作业优先
提高周转时间(cpu处理时间)
- 原理:优先挑选预计执行时间最短的任务来运行。
- 特点:正如你提到的,它能最大限度地降低平均等待时间和平均周转时间,整体吞吐量高。但缺点是可能导致“饥饿”——如果系统里一直有短任务进来,长任务可能永远轮不到执行。
轮转调度
提高响应时间
- 原理:给每个任务分配一个固定的时间片(比如 10ms)。时间片用完,即使任务没执行完,也会被强制暂停并放回就绪队列尾部,等下一轮。
- 特点:它是专门为分时系统设计的,能极大地提高系统的响应时间,让每个用户都感觉系统在同时为自己服务。不过,如果时间片设置得太小,频繁的上下文切换反而会浪费 CPU 性能。
设置优先级
设置优先级,任务的优先级应该动态执行。为了避免某一个进程一直在运行,还需要加入时间片机制。
以下是liunx 0.11 调度算法,动态设置优先级,避免优先级低的任务得不到执行。
yoid
Schedule(yoid)
{ while(1){ c-1;next0;iNR TASKS;
P=&taskINR TASKS];
while(--i){ if((*p->state = TASK RUNNING&&(*p)->counter>c)
c=(*p)->counter,next=i;
if(c)break;//找到了最大的counter
for(p=&LAST TASK;P>&FIRST TASK;--p
(*p)->counter=((*p)
>Counter>>1
+(*p)->priority;)
switch to(next);}
- counter保证了响应时间的界
- 经过io以后, counter就会变大;10时间越长, counter越大(为什么?),照顾了io进程,变相的照顾了前台进程
- 后台进程一直按照counter轮转,近似了sjf调度
- 每个进程只用维护一个counter变量, 简单, 高效
进程切换
把正在执行进程中的信息放到PCB 中,把新的进程的PCB 加载到寄存器中。
多进程同时存在内存会出现两个进程同时读取同一个内存,这就是需要映射表(映射表),把内存分块。
进程的切换分为两个部分:线程的切换,和资源的切换。

用户级线程
线程
进程=资源+指令执行序列
线程=指令执行序列
和进程相比线程更轻,切换更快,一个进程通常包含多个进程。

用户级线程
本质就是切换指令而不切换资源。
用户级线程:

优点
整个过程没有系统调用,没有上下文切换的开销,也没有内存映射的切换,纯粹是在用户态内存里拷贝几个寄存器的值,速度极快
缺点
因为内核不知道它的存在,所以内核只给这个进程分配了一个 CPU 核心。这意味着,即使你的电脑有 16 核,用户级线程也无法利用多核并行。而且,只要其中一个线程发起了系统调用(比如读文件),整个进程都会被内核挂起,导致其他所有线程跟着一起阻塞。
内核级线程
内核级线程示例图:

内核级线程切换
是两套栈进行切换,内核栈切换,对应的用户栈也要切。一般切换过程:“用户态 -> 内核态 -> 用户态”
如果线程中断就启用内核栈。首先先TCB 进行切换,然后内核栈进行切换,最后用户栈进行切换。这就完成了核心级线程的切换

用户级线程和内核级线程对比

时钟中断
为每个进程分配时间片,时间片结束,进程切换。从而实现一台电脑上打开多个程序。
java中的用户线程和核心级线程
- 从 JDK 1.2 开始,Java 放弃了早期的“绿色线程”,主流 JVM(如 HotSpot)全面采用了基于操作系统原生线程的 1:1 内核级线程模型。
- JDK 21 并没有抛弃内核级线程,而是将两者结合。虚拟线程(用户级)负责提供极致的轻量和海量并发能力,而平台线程(内核级)则作为底层基石,负责与操作系统交互并充分利用多核 CPU 的并行能力。它采用了 M:N 混合模型。即大量(M)的虚拟线程会被挂载到少量(N)的平台线程(即底层的内核级线程)上执行。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)