Skip to content

同步与互斥

临界区、互斥锁、信号量、经典同步问题。

Updated View as Markdown
For humans

同步与互斥

并发共享资源的两个问题:互斥(同时只能一个进程进临界区)、同步(执行顺序有要求)。面试主线:原语是什么、经典问题怎么解。

临界区与原子性

  • 临界区:访问共享资源的代码段,同一时刻只允许一个进程进入
  • 原子操作:不可分割的操作(如单条指令),是互斥的基础
  • 互斥的实现要求:忙等要避免(自旋锁忙等浪费 CPU,短临界区可接受)、不能死锁

互斥原语

原语 机制 适用
互斥锁(Mutex) 一个线程持有,其他阻塞等待 临界区互斥
自旋锁 拿不到就忙等(循环检查) 临界区极短、多核
读写锁 读共享、写互斥 读多写少
信号量 计数器,P/V 操作(down/up) 互斥 + 资源计数 + 同步

信号量是通用原语:值为 1 时就是互斥锁,值为 N 时是资源池(如连接池),还用于同步(一个进程等另一个完成)。

P(wait):计数减 1, 小于 0 则阻塞
V(signal):计数加 1, 唤醒等待者

经典同步问题

生产者-消费者: 两个信号量控制空/满

生产者-消费者(高频考点):

empty = N(空位计数), full = 0(已用计数)
生产者: P(empty) → 放入 → V(full)
消费者: P(full) → 取出 → V(empty)

要点:P 的顺序不能反(先拿缓冲区锁再等空位会死锁),缓冲区本身还要一把互斥锁。

哲学家进餐:五个人围桌,两叉子才能吃。解法:同时拿起两把叉子(原子)、限制最多四人同时拿、或奇偶编号错开。考点是预防死锁(见死锁篇)。

读者写者:读者可并发,写者独占。偏好问题:读者优先会饿死写者,写者优先反之。读写锁就是答案。

面试追问

  1. 互斥和同步的区别? 互斥是资源独占(锁),同步是执行顺序(信号量)。信号量都能做
  2. 信号量怎么实现互斥? 初值 1,P 进入 V 离开。初值 N 是资源池
  3. 自旋锁什么时候用? 临界区极短(几条指令):忙等的代价小于阻塞唤醒的代价。单核无抢占场景下自旋甚至可能死锁(持锁进程不被调度),要关中断或让出 CPU
  4. 生产者消费者怎么防止死锁? P 的顺序:先等资源信号量再进临界区。顺序反了会互相持有等待
  5. 读者写者问题? 读写锁:读共享写互斥。读者优先会饿死写者,要有写者优先或公平策略
Navigation

Type to search…

↑↓ navigate↵ selectEsc close