《Java 网络编程基础》12.3 上下文传播与线程安全
本节处理跨线程的请求上下文:ThreadLocal 在线程池中的残留与泄漏、ScopedValue 在 JDK 25 的绑定与恢复、事件循环到业务线程的显式传播,以及不可变消息与 happens-before 如何建立可见性;给出可运行的 RequestContext 与本机输出。
tag
本节处理跨线程的请求上下文:ThreadLocal 在线程池中的残留与泄漏、ScopedValue 在 JDK 25 的绑定与恢复、事件循环到业务线程的显式传播,以及不可变消息与 happens-before 如何建立可见性;给出可运行的 RequestContext 与本机输出。
本节给 linkd 补业务线程池:用有界队列和命名线程隔离阻塞任务,按 CPU 与等待比估算线程数,解释 CallerRunsPolicy 为何会把阻塞带回事件循环,并给出指标与拒绝路径;最后用 JDK 25 虚拟线程做同负载对照,附可复现命令与本机单次数据。
按 libraryd 的借阅计数、事件流水线与仪表盘聚合三条线,整理 volatile、synchronized、ReentrantLock、Condition、原子类、ConcurrentHashMap、六种阻塞队列、同步器、Executors、虚拟线程与 StructuredTaskScope 的关键方法、选型与常见误用,并标注 JDK 25 的预览状态。
2000 个虚拟线程只用了 10 个载体线程,同一个虚拟线程睡一觉就换了载体。本节用三个可复现实验拆开挂起、迁移与 pinning,验证 JDK 24 JEP 491 之后 synchronized 不再 pin,而本地调用仍然占住载体,并给出 Javalin 7 的落地配置。
启动预热要等三件事都完成、数据库同时只能进十个任务、分批导出要四个线程每轮对齐。本节用三组真实运行对比 CountDownLatch、Semaphore 与 CyclicBarrier 的语义差异,给出 libraryd 的 StartupGate、DbConcurrencyGate 与 ExportBarrier 实现,以及各自的失效边界。
借阅事件的审计写库不该拖慢请求线程。本节用 ArrayBlockingQueue 搭一条有界流水线,用 300 个事件、32 个槽位、2 个消费者的饱和实验展示背压与拒绝,再把优雅停止做成可观测的 pending、drained、abandoned 三个数。
用 synchronized 包一个 HashMap 也能线程安全,为什么 libraryd 还要换 ConcurrentHashMap?本节用 800 万次原子与非原子写入、三组键规模的对比实验,说明争用点在哪里,再用 CopyOnWriteArrayList 实现借阅监听器,给出两者的适用边界。
libraryd 需要一条借阅等待队列:没有可借副本时让请求有序等待,有人归还时唤醒其中一个。本节用超时、中断、条件队列三组实验对比 synchronized 与 ReentrantLock,手写一个基于 AQS 的 BooleanLatch,并给出 LoanWaitQueue 的完整实现与边界。
8 个线程各增 100 万次,普通 long 只数到 333 万。本节用真实计数实验比较 AtomicLong 与 LongAdder 的吞吐与适用面,手写一遍 CAS 循环,再用 Treiber 栈复现 ABA 并给出 AtomicStampedReference 的修法,最后落到 libraryd 的 LoanCounters 与 LoanMetrics。
libraryd 的缓存刷新线程写了新值,请求线程却一直读旧的。本节用停止标志与 Dekker litmus 两组可复现实验,量化可见性与重排序,讲清 happens-before 的六条规则,再落到 LifecycleFlag 与 AvailabilityCache 的 volatile 发布写法。
JDK 25 的虚拟线程早已不是预览特性。本节先在同一个 JVM 参数下对比 2000 个平台线程与 2000/100000 个虚拟线程的创建耗时和 RSS,再用 Javalin 7.2.4 的 concurrency.useVirtualThreads 打开虚拟线程,最后用 JFR 确认 synchronized 在 JDK 25 里不再 pin,并说明结构化并发为何仍不进入本卷。
libraryd 的阻塞查询不能直接跑在 Jetty 请求线程上。本节用 ThreadPoolExecutor 把核心线程数、最大线程数、有界队列和拒绝策略讲清楚,并用 2 个线程、3 个队列位的饱和实验展示第 5 个任务之后会发生什么,最后把线程池接进 AppMain 与优雅停机。
深入结构化并发与 Scoped Values:StructuredTaskScope 的 Joiner 模型与 JDK 版本演进、ShutdownOnFailure/ShutdownOnSuccess 语义、自定义 Joiner、ScopedValue 替代 ThreadLocal 的作用域传递、取消传播与虚拟线程固定问题,以及生产迁移与可观测性实践。
系统讲解并发竞态测试的工程化实践:数据竞争与原子性违反、顺序违反三类并发缺陷的识别、Go race detector 与 ThreadSanitizer 的检测原理与局限、确定性复现与调度扰动注入、Loom/Coyote 等模型检查工具、压力测试与随机 sleep 注入、死锁与活锁检测,以及 CI 中的稳定性与种子复现治理。
从调度与隔离模型切入 Swift 并发,讲清结构化并发的任务树与 async let、TaskGroup 的并发语义、取消的协作式传播与检查点、Actor 隔离与可重入陷阱、Sendable 检查与 @MainActor 的 UI 更新约束、AsyncStream 背压策略,并给出数据竞争检测与 Swift 6 严格并发的迁移清单。
PHP 生成器、Fiber 与协程调度实战:Iterator 接口与 yield 语义、惰性序列与内存优势、send/getReturn/throw 双向通信、大文件与数据库游标流式处理、Fiber 的挂起与恢复、状态机与事件循环协作、与 Swoole/ReactPHP 的对比、手写协作式任务调度器。
内核并发原语是驱动、网络栈与文件系统正确运行的底层保障。本文从原子操作与内存屏障的语义差异讲起,梳理 spinlock、mutex、rtmutex、rwsem、seqlock 的适用边界与死锁风险,深入剖析 per-CPU 变量与 RCU 宽限期模型,并给出 lockdep、KCSAN 等工具的实战排查清单。
从 Future 的组合子语义与 ExecutionContext 线程池模型出发,剖析急切求值、无法取消、异常吞噬与阻塞传播四大缺陷,给出 Promise 手动完成与并发原语的实战写法,并对比结构化并发、虚拟线程与 Java 25 的 StructuredTaskScope,最后落到 Cats Effect 与 ZIO 的取舍,以及生产环境的超时、重试、熔断与监控方案。
系统梳理 Combine 的 Publisher/Subscriber/Operator 与常用操作符、AnyCancellable 与 @Published 绑定,以及 async/await 的 Task、async let、TaskGroup、actor、MainActor 与 AsyncSequence,给出互操作桥接、选型取舍与 Swift 6 严格并发下的 Sendable 检查。
pthread_mutex 无竞争时根本不进内核,有竞争时才通过 futex 系统调用挂起线程。本文拆解 futex 的用户态快路径、系统调用操作码、等待队列与唤醒,以及 PI futex 如何用优先级继承解决优先级反转。