月度归档:2026年10月 (59)
AQS(上):一个双向队列,管住天下所有的锁
ReentrantLock、Semaphore、CountDownLatch 源码里全是同一个内核。AQS 三件套:volatile state、双向等待队列、独占与共享——排队调度是天下的公理,判定规则是各家的私法。
原子类全家桶:从 AtomicInteger 到 LongAdder 的分摊艺术
atomic 包五大家族一次认全;AtomicLong 高并发下被 CAS 失败重试拖垮的真相,以及 LongAdder 用 base 加 Cell 数组分摊热点的绝地翻盘——代价是弱一致。
CAS:不加锁也能线程安全,前提是懂它的三个软肋
乐观并发的核心:先改,提交时对暗号。一条 cmpxchg 指令的硬件级原子,AtomicInteger 的 do-while 自旋内核,以及 ABA、自旋空耗、单变量天花板三大软肋。
volatile(下):指令重排与 happens-before 秩序公约
new 一个对象可被重排成三步中的两步,DCL 单例的半成品对象就是这么来的。happens-before 五规则一次讲清,volatile 的完整语义收官。
volatile(上):线程 A 改了变量,线程 B 为什么看不见
一个 while 死循环牵出并发第二宗罪:L1/L2 各核心私有缓存造成的数据割裂,JMM 的主内存/工作内存抽象,以及 volatile 那两条硬性规则——和它治不了的原子性。
synchronized(下):锁升级之路与 wait/notify 两条铁律
无锁、偏向、轻量级、重量级的自动升级链(含 JDK 15 废弃偏向锁的真相);wait 必须在 synchronized 里、等待条件必须写 while——两条铁律背后的道理。
synchronized(上):它锁的不是代码,是对象
三种用法锁三个不同的对象,混用就是三个互不干扰的队列。javap 反编译看 monitorenter 与 ACC_SYNCHRONIZED,以及 Mark Word 里藏着的锁状态。
线程的六种状态:start 和 run 根本不是一回事
t.run() 不是开线程,只是普通方法调用;Java 线程没有 RUNNING 状态;阻塞 I/O 在 jstack 里照样显示 RUNNABLE——三个反直觉,一篇讲透线程生命周期。
并发开篇:一行 i++,库存超卖 100 件
秒杀三分钟,1000 件库存卖出 1100 件,复盘发现罪魁祸首是一行 stock--。并发第一课:你以为的一行代码,CPU 要分三步走,线程随时插队。