CrabNote螃蟹笔记

进程与线程的区别(图解)

图解进程和线程的本质区别,包括内存结构、通信方式、上下文切换、协程对比。

进程与线程的区别(图解) 进程和线程是操作系统的核心概念,面试必问,理解它们对写好并发程序至关重要。 一、基本概念 进程(Process) 程序运行的实例 ,是资源分配的最小单位。 线程(Thread) 进程内的执行单元 ,是 CPU 调度的最小单位。 一个进程可以包含多个线程,它们共享进程的资源。 二、核心区别对比 | 维度 | 进程 | 线程 | | | | | | 资源 | 独立地址空间 | 共享进程资源 | | 开销 | 创建/销毁开销大 | 创建/销毁开销小 | | 切换 | 上下文切换慢 | 上下文切换快 | | 通信 | IPC(管道、消息队列等) | 直接读写共享内存 | | 安全性 | 一个进程崩溃不影响其他 | 一个线程崩溃整个进程崩溃 | | 数量 | 通常几十到几百 | 可以成百上千 | 三、上下文切换 CPU 在多个进程/线程之间快速切换,给人「同时运行」的感觉。 进程切换 需要切换: 虚拟地址空间(页表) 内核栈 寄存器、PC TLB 失效 开销大 :可能消耗几千个时钟周期。 线程切换 同一进程内的线程切换: 不需要切换地址空间 只切换寄存器、PC、栈 TLB 不失效 开销小 :通常几百个时钟周期。 四、进程间通信(IPC) 由于进程内存隔离,需要专门的 IPC 机制: | 方式 | 特点 | 场景 | | | | | | 管道 (Pipe) | 半双工、有亲缘关系 | 父子进程 | | 命名管道 (FIFO) | 任意进程 | 简单通信 | | 消息队列 | 内核维护 | 异步通信 | | 共享内存 | 最快 | 大数据量 | | 信号量 | 同步互斥 | 锁机制 | | 信号 | 异步通知 | 中断 | | Socket | 跨网络 | 网络通信 | 共享内存示例 五、线程间通信与同步 线程共享内存,通信简单,但 需要同步 防止数据竞争: 同步方式 互斥锁(Mutex) :保护临界区 读写锁 :读多写少场景 条件变量 :等待通知 信号量(Semaphore) :控制并发数 自旋锁 :短临界区 六、协程(Coroutine) 更轻量级的「用户态线程」。 | 维度 | 进程 | 线程 | 协程 | | | | | | | 调度 | 内核 | 内核 | 用户态 | | 切换开销 | 大 | 中 | 小 | | 数量 | 几十 | 几百/千 | 几万/十万 | | 编程模型 | 阻塞 | 阻塞 | 同步非阻塞 | Go 语言的 goroutine Go 的 GMP 调度器让成百万 goroutine 高效运行。 七、实战:多线程问题 1. 竞态条件 2. 死锁 死锁四个必要条件 : 1. 互斥 2. 持有并等待 3. 不可剥夺 4. 循环等待 3. 内存可见性 八、面试高频题 Q1:线程和进程的区别? 一句话: 进程是资源分配的最小单位,线程是 CPU 调度的最小单位 。 详细:进程独立内存,线程共享进程内存;进程开销大,线程开销小。 Q2:多线程一定比单线程快吗? 不一定。 IO 密集型 :多线程快(IO 时 CPU 可以做别的) CPU 密集型 :线程数 CPU 核数反而更慢(切换开销) Q3:协程的优势? 用户态调度,开销极小 单机可创建海量协程 同步编程模型,更易理解 Q4:如何避免死锁? 破坏四个必要条件之一 固定加锁顺序 使用 tryLock + 超时 死锁检测 九、小结 | 概念 | 一句话 | | | | | 进程 | 资源分配单位 | | 线程 | CPU 调度单位 | | 协程 | 用户态轻量级线程 | | 上下文切换 | 进程切换 线程切换 | | IPC | 进程间通信 | | 同步 | 线程间协作 | 小宇宙提醒:并发编程的本质是 协调多个执行流对共享资源的访问 ,掌握锁和通信是关键。