1. 进程操作系统中的独立小宇宙第一次接触进程这个概念时我总把它想象成一个个独立运行的宇宙。每个进程都拥有自己的内存空间、代码段和数据段就像宇宙中的星系互不干扰。考研复习时最常遇到的困惑就是进程和程序到底有什么区别程序就像菜谱而进程则是按照菜谱实际做菜的过程。同一个菜谱程序可以同时被多个厨师进程使用每个厨师都有自己的操作台内存空间。这里有个实际案例当你同时打开三个Word文档时任务管理器里会出现三个winword.exe进程它们共享相同的程序代码但各自处理不同的文档数据。进程控制块(PCB)是操作系统的核心数据结构我习惯把它比作进程身份证。在Linux内核中PCB其实就是task_struct结构体包含进程状态、PID、程序计数器等关键信息。下面是一个简化版的PCB结构struct task_struct { long state; // 进程状态 pid_t pid; // 进程ID unsigned long flags; // 进程标志 struct mm_struct *mm; // 内存管理信息 // ... 其他字段 };进程状态转换是常考的重点我总结了一个记忆口诀就绪等CPU运行正干活阻塞等资源。特别要注意的是从阻塞态不能直接进入运行态必须先回到就绪队列排队。这个细节在2019年408统考中就出现过。2. 线程轻量级进程的妙用线程的概念曾让我头疼了很久直到在实验室用Java写多线程下载器时才真正理解。线程是进程内的执行单元共享同一地址空间但各自拥有独立的栈和寄存器。这就好比办公室里的同事线程共用打印机进程资源但各自处理不同的工作任务。考研中常考的线程实现方式主要有两种用户级线程像Python的threading模块切换快但无法利用多核内核级线程如Java的线程能利用多核但切换成本高实际编程时我踩过不少线程同步的坑。比如用C写多线程程序时如果不加锁就修改共享变量就会出现竞态条件。这里有个经典案例#include thread int counter 0; // 共享变量 void increment() { for(int i0; i100000; i) counter; // 这里会出现竞态条件 } int main() { std::thread t1(increment); std::thread t2(increment); t1.join(); t2.join(); std::cout counter; // 结果通常小于200000 }解决方法是使用互斥锁mutex这是操作系统原理中临界区保护的具体实现。在考研复习时建议结合具体编程语言理解这些抽象概念。3. 同步与互斥进程间的舞蹈进程同步就像跳交谊舞需要精确的配合。我在学习这个概念时用食堂打饭的场景来理解互斥打饭窗口一次只服务一个同学临界资源独占同步必须先刷卡付款才能拿到饭菜执行顺序约束信号量是解决同步问题的利器它的P/V操作原语看似简单却容易混淆。我的记忆方法是P操作荷兰语proberen尝试获取资源相当于减一V操作荷兰语verhogen释放资源相当于加一下面是用C语言模拟生产者-消费者问题的代码片段这是考研中的经典案例sem_t empty, full, mutex; void producer() { while(1) { sem_wait(empty); // 等空位 sem_wait(mutex); // 进入临界区 /* 生产物品 */ sem_post(mutex); // 离开临界区 sem_post(full); // 增加物品 } }管程(monitor)是更高级的同步机制Java中的synchronized关键字就是管程的实现。考研复习时要特别注意条件变量的使用这是管程的核心要素。4. 死锁系统运行的交通堵塞第一次在实验室遇到死锁时我的多线程程序完全卡死就像十字路口四方向都被堵住的车辆。死锁的四个必要条件一定要烂熟于心互斥条件资源一次只能一个进程使用占有并等待拿着资源A等资源B非抢占条件资源不能被强制拿走循环等待形成进程-资源的环形链银行家算法是避免死锁的经典方法我把它想象成银行贷款审批每个进程声明最大需求贷款额度系统检查分配后是否仍处于安全状态银行保留足够资金只有安全时才分配资源批准贷款在实际编程中我总结了几条避免死锁的经验按固定顺序获取锁如总是先锁A再锁B使用带超时的锁获取机制尽量减少临界区代码量用工具如Valgrind检测潜在死锁死锁检测算法中资源分配图是重点。2018年考研真题就出现过画图题要求根据资源分配图判断是否存在死锁。我的解题技巧是找图中是否存在不可完全化简的环路。