两个线程同时给同一个计数器加 1,看起来很小的一件事,最后结果却可能少加一次。
原因其实很简单。count++ 在源码里是一行,机器执行时通常要经历读取、计算、写回几个步骤。线程 A 刚读到旧值,还没写回;线程 B 也读到了同一个旧值。两边各自算出新值,最后写回的却是同一个结果。
为了避免这类并发问题,操作系统提供了锁和一系列同步机制。它们要解决的问题不只是一段代码能不能同时执行,还包括线程该不该阻塞、资源数量怎么控制、条件不满足时怎么等待。到了内核里,还要继续考虑中断、抢占、多 CPU、实时性和调度延迟。
这篇文章只讲操作系统视角下的同步机制。Java 里的 synchronized、ReentrantLock、AQS、CAS 和锁优化已经在 Java 锁详解 里展开过,这里不会重复那套内容。本文重点看 mutex、semaphore、condition variable、spinlock、futex 这些概念各自解决什么问题。等理解了这些同步原语,再去看 死锁详解,就更容易看懂“等待关系为什么会绕成环”。
2026/6/15大约 21 分钟
