并发控制

这页讲的是:Linux 内核里很多代码并不是按单线程顺序跑的,CPU、内核线程、中断、软中断可能同时碰同一份数据,因此必须认真处理并发正确性。学这页的关键,不是死记某种锁的实现,而是建立“为什么内核几乎处处都在防止同时乱动”的感觉。

这块是什么

并发控制不是单独一个“业务模块”,而是贯穿整个内核的基础能力。它负责保证:当多个执行路径同时访问同一资源时,数据不会被破坏,状态不会变乱,系统不会因为竞态条件而偶发出错。和应用层不同,内核不仅要处理线程之间的并发,还要处理不同 CPU、不同上下文、硬件事件和后台处理之间的并发。

可以把它理解成:很多人同时改同一张表,系统必须规定“谁先动、谁等一下、谁可以只读、谁必须独占”,否则表很快就乱了。

它负责什么

保护共享数据

  • 避免多个执行流同时乱改同一对象
  • 确保状态转换有顺序
  • 减少竞态条件
  • 避免“平时没事,偶尔炸一次”的随机错误

协调不同执行上下文

  • 进程上下文
  • 中断上下文
  • 软中断和延后执行
  • 让不同环境下的代码能按各自规则安全协作

平衡正确性与性能

  • 减少不必要的等待
  • 控制锁竞争
  • 兼顾可扩展性
  • 避免“修对了但跑得很慢”的另一类失败

为什么内核里的并发更麻烦

来源你现在怎么理解为什么会变难
多核 CPU多个核可以同时执行不同代码路径。不再是“轮流执行”的假象,而是真的同时动同一份状态。
任务切换同一个任务可能在任意点被切走,另一个任务接着运行。任何共享结构都要考虑切换点带来的时序变化。
中断硬件事件可能突然打断当前执行流。某些代码不能睡眠,能用的同步手段也随之受限。
后台工作workqueue、软中断、定时器回调等会在别的上下文继续处理事情。“看起来一段逻辑”其实可能分散在多个时间点和上下文里完成。

关键概念

概念现在怎么理解
自旋锁短时间等待时常用的锁,拿不到就原地转,适合不能睡眠的场景。
互斥锁适合进程上下文里较长时间的互斥访问,拿不到可以睡眠等待。
原子操作由硬件和指令保证某些最小操作不可被打断。
RCU一种偏重“读多写少”场景的同步机制,让读取路径更轻量。
中断上下文某些代码是在响应硬件事件时执行,约束比普通线程更多。

拿锁之前,内核大概在想什么

问题为什么要先想清楚
这个路径能不能睡眠能不能睡眠,直接决定能用互斥锁还是必须用更轻量但更受限的手段。
竞争会不会很频繁如果大家都在抢同一把锁,正确性虽然保住了,性能却可能崩掉。
读多还是写多不同访问模式适合不同同步思路,RCU 就是典型例子。
这个共享状态会跨哪些上下文如果同时被普通线程和中断路径访问,就不能只按“线程之间互斥”去想。

为什么重要

常见误解

它不负责什么

和其他模块的关系

相关模块关系
调度器任务什么时候切换,会影响锁什么时候被持有和释放。
内存管理页表、缓存、回收链表等都需要同步保护。
文件系统目录项、inode、页缓存等共享结构并发很多。
驱动 / 中断硬件事件和普通执行流可能同时访问设备状态。

读完这页后,你应该能回答

后面适合继续问:为什么某些上下文里不能睡眠?RCU 和锁的思路差别是什么?锁竞争为什么会变成性能问题?