Skip to content

同步与互斥

同步与互斥(Synchronization & Mutual Exclusion)是并发编程的核心难题——多个线程/进程共享同一份资源时,如何协调它们的执行顺序与访问规则,使其结果正确不阻塞死。它有两层目标:①互斥(Mutual Exclusion)——保证同一时刻只有一个线程进入临界区(访问共享资源的代码段),避免竞态条件(race condition);②同步(Synchronization)——让线程按特定顺序协作(如生产者先放数据,消费者才能取)。互斥锁、信号量、管程是三大经典工具,Peterson 算法是软件互斥的理论奠基,而生产者-消费者、读者-写者、哲学家就餐是三大经典问题,优先级反转则是真实系统(如火星探路者号)踩过的坑。

本叶的全部考点围绕"临界区怎么保护、并发怎么协调"展开:①竞态条件——为何并发会出错(计数器 i++ 丢失更新),根因是指令交错;②临界区问题四条件——互斥、前进、有限等待、(与速度无关);③互斥锁(mutex)——最朴素的互斥原语,加锁/解锁,二元状态;④信号量(semaphore)——Dijkstra 提出,P/V 操作,二元信号量(等价 mutex)与计数信号量(资源池);⑤mutex vs semaphore 区别——所有权与释放者;⑥三大经典问题——生产者-消费者(empty/full + mutex)、读者-写者(读者优先 vs 写者优先)、哲学家就餐(死锁风险与解法);⑦管程(monitor)——语言级封装(条件变量 wait/signal),比信号量易用;⑧Peterson 算法——两进程软件互斥,flag + turn;⑨优先级反转——低优先级持锁阻塞高优先级,优先级继承/天花板协议解决;⑩自旋锁 vs 阻塞锁——忙等与睡眠的取舍。掌握这些,是写出正确并发程序(无数据竞争、无死锁、无饿死)的前提。

评价

优点

  • 互斥保证安全:临界区同一时刻只允许一个线程进入,消除竞态条件,保证共享数据一致
  • 同步协调顺序:信号量/条件变量让线程按预期顺序协作(如先生产后消费),实现复杂并发协议
  • 抽象降低复杂度:管程(Java synchronized/Go sync.Mutex)把锁与条件变量封装成语言级结构,开发者无需手写 P/V
  • 广泛适用:从单机多线程到分布式锁,互斥思想贯穿所有并发场景

缺点

  • 死锁风险:多个线程互相等待对方释放锁(如哲学家同时拿起左手叉子),不加防护会永久僵死
  • 性能损耗:加锁/解锁有上下文切换与缓存失效开销;锁粒度太粗降低并发度,太细又难维护
  • 优先级反转:高优先级线程被低优先级线程间接阻塞,可能导致实时系统任务超时(火星探路者号事故)
  • 极难调试:竞态、死锁等 bug 非确定可重现,只在特定时序下触发,是测试与诊断的重灾区

本叶地图

  • 入门 —— 竞态条件、临界区问题四条件、互斥锁、信号量(二元/计数)、mutex vs semaphore 区别
  • 经典同步问题 —— 生产者-消费者、读者-写者(读者优先/写者优先)、哲学家就餐(死锁与解法),含信号量伪代码详解
  • 管程、优先级反转与 Peterson 算法 —— 管程与条件变量、Peterson 软件互斥、优先级反转与继承、自旋锁 vs 阻塞锁
  • 参考 —— mutex/semaphore/管程对比、经典问题信号量配置速查、代码模板、易错点

幻灯片地址

同步与互斥

测试题

同步与互斥测试题