⚙️ 进程与线程
进程/线程/协程 · 进程间通信 · 用户态内核态 · 调度算法
1. 进程、线程、协程的区别?
- 进程:资源分配的最小单位——独立的地址空间(虚拟内存)、文件描述符、PCB(进程控制块)。进程间隔离,切换开销大(地址空间切换)
- 线程:CPU 调度的最小单位——同一进程内线程共享地址空间和文件描述符,各有独立栈和寄存器上下文。切换开销小
- 协程(轻量线程):用户态调度,无内核切换。一个线程内可以跑成千上万个协程(Go goroutine、Java 21 虚拟线程)
🎯 面试要点
- 进程 = 资源边界 + 隔离;线程 = 并发执行;协程 = 超高并发(IO 密集场景)
- 线程模型:1:1(Java 线程 = 内核线程,创建成本高)→ 用户态 M:N(协程)
- Java 21 的虚拟线程(Virtual Threads)就是协程式线程——提一句显前沿
2. 进程间通信(IPC)方式?
- 管道(Pipe):半双工字节流,父子进程/管道符(`|`)。无名管道限亲缘关系;命名管道(FIFO)不限
- 消息队列:内核维护的消息链表,有类型、有边界(对比字节流)
- 共享内存:最快的 IPC——映射同一块物理内存,无拷贝。需配信号量同步(否则竞态)
- 信号量:计数器,PV 操作,同步与互斥
- 信号(Signal):异步通知(SIGKILL、SIGTERM、SIGSEGV)
- Socket:跨机器通用(TCP/UDP/Unix Socket)——分布式系统的 IPC 基础
🎯 面试要点
- 线程间通信更轻:共享内存(进程内天然共享)+ 锁/条件变量
- Java 的 IPC 抽象:RMI/Socket/NIO;跨进程共享内存用 MappedByteBuffer
- 排序:共享内存 > 消息队列 > 管道 > Socket(性能)
3. 用户态与内核态?系统调用?
- 内核态:操作系统核心代码运行态,可访问硬件和所有内存(特权指令)
- 用户态:应用程序运行态,受限(无法直接访问硬件/内核内存)
- 切换:应用需要内核能力(读写文件、网络、创建线程)→ 系统调用(syscall)→ 陷入内核态执行 → 返回用户态。每次切换有开销(保存上下文 + 模式切换)
- 触发方式:系统调用、中断(硬件)、异常(缺页/除零)
🎯 面试要点
- 高并发性能优化核心之一:减少系统调用/内核切换(零拷贝、批量、用户态协议栈)
- 上下文切换 = 线程切换成本:线程数不是越多越好(见并发模块线程池)
4. 进程调度算法?
- FCFS(先来先服务):公平但长任务阻塞(convoy effect)
- SJF(短作业优先):平均等待最短,但长作业可能饿死
- 时间片轮转(RR):每个进程轮流跑一个时间片,交互式友好
- 优先级调度:高优先级先跑,低优先级饿死 → 配合老化(aging 提升等待时间长的进程优先级)
- 多级反馈队列(MLFQ,现代 OS 实际用):多级队列 + 时间片递增 + 高优先级优先——兼顾交互(I/O 型)和计算(CPU 型)
🎯 面试要点
- Linux CFS(完全公平调度):按虚拟运行时间(vruntime)排序,红黑树选最小——公平基于"等待时长"
- I/O 密集型进程应优先(它很快让出 CPU),MLFQ 的实现思路