1. 死锁的四个必要条件?如何预防?

  1. 互斥:资源一次只能被一个进程使用(无法避免——锁的本质)
  2. 持有并等待:进程持有资源又在等别的资源
  3. 不可剥夺:资源只能主动释放
  4. 循环等待:存在等待环(P1 等 P2、P2 等 P1…)

预防策略(破坏任意一个非互斥条件):

🎯 面试要点

  • 与并发模块呼应:MySQL 死锁、JVM 死锁都是同一理论
  • 死锁检测 vs 预防:银行家算法(避免,靠安全序列)、资源分配图(检测环)

2. 什么是上下文切换?代价多大?

上下文切换:CPU 从一个线程/进程切到另一个——保存当前上下文(寄存器、程序计数器、栈指针、页表/缓存状态),加载新上下文。

代价:

减少切换:线程数匹配 CPU 核数(线程池大小设置)、避免锁竞争(阻塞=切换)、协程(用户态切换,无内核开销)

🎯 面试要点

  • vmstat 的 cs(context switch)列过高 = 切换频繁,配合线程池优化
  • 为什么"线程不是越多越好":每个阻塞线程都在消耗切换成本

3. 僵尸进程和孤儿进程?

处理:查 ps aux | grep Z;僵尸的父进程是关键——修复父进程(回收逻辑)或 kill 父进程让 init 收养;kill 僵尸PID 无效(它已死)。

🎯 面试要点

  • Java 中 Runtime.exec / ProcessBuilder 必须 waitFor/销毁,否则子进程僵死
  • ps 状态列:R 运行、S 睡眠、D 不可中断(IO 等待)、Z 僵尸、T 停止

4. 其他高频考点速览?

🎯 面试要点

  • 局部性原理是贯穿性考点:CPU 缓存、PageCache、Redis、JVM 分层编译都能引用它
  • 自旋 vs 互斥的选择就是"临界区长短"的权衡——与 synchronized 锁升级对照记忆

🎤 常见面试追问

  1. 死锁四个必要条件?(必背)——互斥、持有并等待、不可剥夺、循环等待。破坏任意一个(非互斥)可预防;最实用的是破坏循环等待(资源排序加锁)。
  2. 僵尸进程怎么处理?——父进程没 wait() 回收导致。kill 僵尸无效(已死);修父进程回收逻辑,或杀父进程让 init 收养。ps 状态 Z 就是僵尸。
  3. 自旋锁和互斥锁怎么选?——临界区短(自旋快,忙等省切换)→ 自旋;临界区长(睡眠省 CPU)→ 互斥。JVM 的轻量级锁自旋同理。
  4. 惊群效应是什么?——多个进程/线程同时等同一事件,唤醒全部但只有一个能用(浪费)。epoll 的 EPOLLEXCLUSIVE、Nginx accept 锁解决。
  5. 局部性原理是什么?——时间局部性(刚用的还会用)+ 空间局部性(附近的会用到)——CPU 缓存/PageCache/预取的理论基础。

📖 名词解释(本页术语)

术语 大白话解释
死锁多个任务互相持有对方要的资源,谁也不放。四条件:互斥/持有等待/不可剥夺/循环等待。
僵尸进程 / 孤儿进程僵尸:子进程退出但父进程没回收(占 PID);孤儿:父进程先退,被 init 收养。
自旋锁拿不到锁就忙等(循环检查)——适合短临界区,省上下文切换。
信号量(Semaphore)计数器同步机制:PV 操作(P 拿 V 放)。可控制 N 个资源;互斥锁是它的 0/1 特例。
惊群效应一事件唤醒多个等待者,只有少数有用——浪费。高并发服务器要避免。
局部性原理程序访问有"聚集性":时间上刚用的还会用,空间上附近的会用到——缓存体系的理论基石。
银行家算法死锁避免算法:分配前检查是否安全(能否找到安全序列)。理论价值为主。
⚠️ 本页面由 AI 生成,内容仅供参考,请以官方文档和实际源码为准。