{"name":"并发编程","id":"编程语言-并发编程","content":"# 并发编程\n\n## 并发的本质\n\n### 并发系统模型\n\n并发真正要解决的问题是：**多个执行主体在不确定时间顺序下，对状态进行协作的问题。**\n\n```text\n并发系统 = 执行单元（谁在运行） + 状态（谁被修改） + 时间交错（顺序是否确定） + 协调机制（如何避免冲突）\n```\n\n### 并发的核心矛盾\n\n```text\n共享（协同）vs 隔离（避免冲突）\n```\n\n所有并发模型都在这两个极端之间权衡：\n\n| 模型     | 倾向  |\n| ------- | ---- |\n| Actor   | 隔离  |\n| CSP     | 隔离  |\n| STM     | 共享  |\n| 线程+锁  | 共享  |\n\n## 并发问题分析\n\n### 充分必要条件\n\n并发问题必须同时满足三个条件：**多个执行主体 + 共享可变状态 + 时间交错**。\n\n消除任意一个条件：\n\n| 消除项   | 结果  |\n| ----- | --- |\n| 不共享   | 无竞争 |\n| 不可变   | 无修改 |\n| 无时间交错 | 无并发 |\n\n> 并发问题不在于线程，而是共享。\n\n### 错误统一抽象\n\n并发错误本质上是**协调失效**：\n\n| 类型 | 含义 | 本质 |\n| --- | --- | --- |\n| 安全性 | 不做错事 | 状态协调失效 |\n| 活跃性 | 系统持续推进 | 进度协调失效 |\n\n#### 状态协调失效（安全性）\n\n三个永恒问题：\n\n| 问题  | 本质       | 根源           |\n| --- | -------- | ------------ |\n| 可见性 | 修改是否被观察到 | 缓存 / 重排      |\n| 原子性 | 操作是否被打断  | 时间交错         |\n| 有序性 | 执行顺序是否一致 | 编译器 / CPU 优化 |\n\n错误本质：**基于已经失效的观察结果做出了决策。**\n\n| 问题     | 本质     | 具体含义                                                  |\n| ------ | ------ | ----------------------------------------------------- |\n| 竞态条件   | 观察失效  | 观察到状态为 X，基于它做决策，但在决策提交前另一个线程已把状态改成 Y，导致决策基于失效前提 |\n| 脏读     | 观察滞后  | 读到另一个线程正在修改但尚未提交的值，这个值可能回滚或被覆盖                     |\n| 双重创建   | 状态失真  | 对象构造期间（构造函数未执行完），状态还不完整就被其他线程看到                  |\n| ABA 问题 | 时间错觉  | 观察到的值与之前相同（A），但中间经历了 A→B→A 的完整迁移，掩盖了状态变化的历史    |\n\n不变式（Invariant）是对象在生命周期中必须始终保持的业务条件，例如账户余额 >= 0、订单状态不可逆。所谓的线程安全是：**无论执行顺序如何，对象始终维持其不变式（Invariant）。**\n\n```text\n线程安全 = 不变式始终成立\n```\n\n#### 线程安全分类\n\n| 分类      | 含义         | 风险来源        | 需要同步       | 代表             |\n| ------- | ---------- | ----------- | ---------- | -------------- |\n| 不可变安全  | 天然线程安全     | 无（状态不可变）   | 不需要         | String、final 字段  |\n| 封闭安全   | 不共享        | 无（执行单元私有）  | 不需要         | 栈变量、ThreadLocal |\n| 相对安全   | 单操作安全      | 复合操作被打断     | 需要（针对单操作） | AtomicInteger    |\n| 组合不安全  | 多步骤破坏不变式   | 业务不变式未被保护   | 需要（业务层面）   | 多字段组合的业务对象   |\n\n锁、CAS、事务都只是维护不变式的手段。\n\n```text\n共享 + 可变 + 未受控访问 = 不安全\n```\n\n设计优先级：不共享 > 不可变 > 消息通信 > 乐观协调 > 互斥锁\n\n#### 进度协调失效（活跃性）\n\n活跃性问题的本质是：**协调结构失效导致无法推进**，各方对\"对方会让步\"的假设循环依赖。\n\n| 问题 | 本质 | 具体表现 |\n| --- | --- | --- |\n| 死锁 | 循环资源等待 | 线程互相持有对方需要的锁，都阻塞等待 |\n| 活锁 | 持续协商但永不成功 | CPU 繁忙但系统无进展，始终在响应但无法推进 |\n| 饥饿 | 长期得不到调度机会 | 某些线程永远无法获得所需资源 |\n\n死锁：循环资源等待。Coffman 条件：互斥、占有等待、不可剥夺、循环等待。\n\n活锁：持续协商但永不成功。特点：CPU 很高，系统无进展。\n\n饥饿：长期得不到调度机会。典型：优先级反转、非公平锁。\n\n## 内存模型：并发世界的抽象规范\n\n### 内存模型是什么\n\n内存模型是**多线程环境下内存访问行为的抽象规范**，回答的核心问题是：\n\n> **一个线程的内存操作，何时对另一个线程可见？**\n\n它是硬件能力与编程语言之间的**契约层**——约定了你能期望什么，而不需要关心硬件怎么实现。\n\n### 为什么需要内存模型\n\n现代硬件为了性能做的事：\n\n| 优化 | 导致的问题 |\n| --- | --- |\n| CPU 缓存 | 线程看不到其他线程的修改（**可见性问题**） |\n| 指令重排 | 程序顺序与执行顺序不符（**有序性问题**） |\n| 异步写入 | 复合操作被打断（**原子性问题**） |\n\n内存模型定义：**当程序员写了 X 代码，真实执行时 Y 行为是否可以接受**。\n\n### 内存模型定义三个保证\n\n| 保证 | 解决什么问题 |\n| --- | --- |\n| 可见性保证 | 写入何时对线程可见（为什么他看不到我的修改） |\n| 有序性保证 | 哪些操作顺序是强制的（重排到什么时候是错的） |\n| 原子性保证 | 哪些操作是不可分割的（复合操作怎么保证完整） |\n\n### happens-before：跨线程的保证\n\nhappens-before 是**可见性 + 有序性**的组合保证：\n\n```text\nA happens-before B\n=\nB 能看到 A 的结果\n且\nA 在 B 之前排序\n```\n\n它不是时间概念，而是语言层（Java JMM / C++ Memory Model / Rust Send/Sync）共同遵守的理论基础。\n\n### 内存模型的光谱\n\n不同硬件的\"一致性代价\"不同：\n\n| 类型 | 特点 | 代表 |\n| --- | --- | --- |\n| 强顺序（TSO） | 代价内化，始终慢 | x86 |\n| 弱顺序 | 代价显式，平时快，需要时贵 | ARM, PowerPC |\n| 顺序一致 | 所有线程看到一致顺序 | 默认模型 |\n\n```\n强顺序模型：硬件帮你做所有屏障，编程简单但始终有开销\n弱顺序模型：需要时手动加屏障，性能更好但编程复杂\n```\n\n### 硬件到语言的链路\n\n```text\n硬件（CPU 缓存 / 重排 / 原子指令）\n    ↓ 提供能力\n内存模型（定义契约）\n    ↓ 提供语法\n语言（Java volatile / C++ memory_order / Rust Send/Sync）\n    ↓\n程序员（使用 API）\n```\n\n硬件负责\"能做到什么\"，内存模型负责\"做到了什么效果\"——这是必要的抽象层，让软件在不同硬件上有一致行为。\n\n## 并发实践\n\n### 并发控制哲学\n\n并发控制不是\"保护代码\"，而是**协调状态访问顺序**——即并发系统四要素中\"协调机制\"的落地。所有控制手段按是否保留冲突分为两层：\n\n| 层级 | 思路 | 策略 | 回扣 |\n| --- | --- | --- | --- |\n| 消除型 | 让并发问题不成立 | 隔离（消共享）、不可变（消可变） | 充要条件表、线程安全分类 |\n| 协调型 | 冲突存在，管理它 | 乐观（假设冲突少）、悲观/互斥（假设冲突多） | 悲观与乐观差异 |\n\n**统一优先级**：消除 > 协调，即 `不共享 > 不可变 > 消息通信 > 乐观 > 互斥`。共享越少，复杂度越低。\n\n#### 消除型：从根源让问题不存在\n\n锁是共享之后的补救，隔离与不变则从根源消灭竞争。\n\n```text\n最好的锁 = 不存在的锁\n```\n\n| 手段 | 本质 | 条件 |\n| --- | --- | --- |\n| 隔离（线程封闭） | 对象仅属单执行单元（栈变量、协程局部、Actor 内部状态） | 不逸出执行单元 |\n| 不可变 | 共享不可避免时，共享不可变状态 | 状态不可改 + final（禁重排）+ 构造期不逸出 |\n\n二者共同点：无需同步、无需可见性保证、无时间问题。\n\n#### 协调型：冲突存在时如何管理\n\n二者分歧在**对冲突概率的假设**：\n\n| 维度 | 悲观/互斥 | 乐观 |\n| --- | --- | --- |\n| 假设 | 冲突一定发生 | 冲突是小概率 |\n| 策略 | 先限制，再执行 | 先执行，冲突再处理 |\n| 典型 | Mutex、synchronized、数据库锁 | CAS（先执行失败重试）、版本（MVCC、COW 快照读） |\n| 代价 | 阻塞、上下文切换、死锁风险 | 重试、ABA、自旋消耗（CAS 系） |\n\n### 安全发布\n\n并发问题很多不是\"锁问题\"，而是**发布时机问题**：对象在构造完成前就进入了共享域，再完美的锁保护的也是半成品。\n\n**发布**：对象从私有域进入共享域（放入缓存、注册监听器、返回给其他线程）。\n\n**逸出 = 失控的发布**：对象在未准备好前被其他执行单元访问。最危险情况是构造期间 `this` 逸出（注册监听器、启动内部线程），导致 final 语义失效、对方读到不完整对象。\n\n安全发布的本质不是\"有没有加锁\"，而是**是否建立了 happens-before**。因为 happens-before 同时保证：\n\n- **可见性**——构造期的所有写入都已刷出，对方不会读到 null 或旧值\n- **有序性**——构造完成排在发布之前，对方看到的必然是完整对象\n\n四种安全发布手段，本质都是在\"发布\"这一时间点建立 happens-before，区别只在途径：\n\n| 手段 | 建立 happens-before 的途径 |\n| -------- | -------- |\n| 静态初始化 | JVM 类加载锁保证初始化先于任何使用 |\n| final 字段 | 构造结束的 freeze 屏障，对正确发布的对象可见 |\n| volatile | 写-读屏障传递可见性与有序性 |\n| 锁保护发布 | 解锁 happens-before 后续加锁 |\n\n### 性能与伸缩性的本质\n\n并发不是免费的。其代价与上限由两条根本定律决定，\"减少共享\"等优化口诀都是它们的推论。\n\n#### 伸缩性的两个天花板\n\n| 定律 | 结论 | 含义 |\n| --- | --- | --- |\n| Amdahl 定律 | 加速比上限 = 1 / 串行占比 | 串行部分决定天花板，再多核也无法突破 |\n| USL（通用伸缩性定律） | 在 Amdahl 上叠加**一致性开销**项 | 该项随并发数二次增长，故加核到一定程度**反而变慢** |\n\n**真正限制伸缩性的不是 CPU，而是共享热点**——共享导致的一致性流量正是 USL 里那个二次恶化项。所以现代系统的演化方向是：**共享最小化 + 局部性最大化**。局部性之所以关键：共享的真实粒度是物理缓存行而非逻辑变量——逻辑上不相干的数据若落在同一缓存行，仍构成共享热点（即伪共享）。\n\n#### 代价的三个来源\n\n并发损耗并非单一，分属不同抽象层：\n\n| 来源 | 成本 | 抽象层 |\n| --- | --- | --- |\n| 调度 | 上下文切换 | OS |\n| 一致性 | 缓存失效、内存屏障（Fence） | 硬件 / 内存模型 |\n| 串行化 | 锁竞争 | 算法 / Amdahl 串行占比 |\n\n后两类直接回扣内存模型章——缓存与屏障的代价，在伸缩性层面显形为一致性开销。\n\n#### 锁竞争的量化\n\n临界区的串行化程度近似排队论的**利用率**：\n\n```text\nρ ≈ 到达率 × 持锁时间\n```\n\nρ 越接近 1，等待越剧烈。优化顺序据此推出：**减少共享（降到达率）> 缩短临界区（降服务时间）> 优化锁（降单次开销）**。\n\n**并发目标不是线程更多，而是等待更少。**\n\n## 并发模型的统一分类\n\n并发模型看似繁多，实则由两条正交的设计轴决定：**怎么通信**与**安全从哪来**。两轴定义一个坐标平面，所有模型都是其中的坐标点。\n\n### 第一维：通信机制\n\n| 模型 | 协作方式 | 特点 | 代表 |\n| --- | --- | --- | --- |\n| 共享内存 | 我修改，你直接看到 | 灵活、高性能、容易失控 | Java Threads、pthreads |\n| 消息传递 | 我修改，告诉你，你再处理 | 隔离性强、易扩展、延迟更高 | Actor、CSP |\n\n### 第二维：安全保证来源\n\n| 约束 | 时机 | 特点 | 代表 |\n| --- | --- | --- | --- |\n| 动态约束 | 运行时发现错误 | 灵活、容易遗漏 | 锁、CAS、STM |\n| 静态约束 | 编译期证明安全 | 强约束、更安全 | Rust Ownership、线性类型系统 |\n\n### 两维坐标：模型的统一定位\n\n把典型模型放进 `(通信 × 安全)` 平面，分类才真正\"统一\"：\n\n|  | 动态约束（运行时） | 静态约束（编译期） |\n| --- | --- | --- |\n| **共享内存** | 锁、STM | Ownership |\n| **消息传递** | Actor、CSP | 会话类型（Session Types，前沿） |\n\n坐标暴露两条规律：\n\n- **同一通信方式下，安全轴决定代价时机**：共享内存里，锁/STM 把检查推迟到运行时，Ownership 提前到编译期——同源不同时。\n- **空格即演进方向**：消息传递 + 静态约束 长期是空白，会话类型正是在填补它（编译期证明通道协议不出错）。\n\n### 典型并发模型：各自的取舍\n\n定位之后看细节——每个模型都不消灭复杂度，只**转移**复杂度：\n\n| 模型 | 坐标 | 本质 | 消除的问题 | 转移出的复杂度 |\n| --- | --- | --- | --- | --- |\n| 锁模型 | 共享 / 动态 | 控制共享 | 数据竞争 | 死锁 |\n| Actor | 消息 / 动态 | 封装状态 | 共享问题 | 消息一致性 |\n| CSP | 消息 / 动态 | Channel 协作 | 显式锁 | 通道阻塞 |\n| STM | 共享 / 动态 | 内存事务 | 锁管理 | 回滚成本 |\n| Ownership | 共享 / 静态 | 类型隔离 | 数据竞争 | 生命周期复杂度 |\n\n\"转移出的复杂度\"列揭示一条守恒律：选型不是挑\"最好的模型\"，而是选**愿意承受哪一类复杂度**。\n\n## 现代并发演化\n\n并发的根本困难是**共享状态 + 时间不确定性**。看似纷繁的现代技术，实则沿四条同向矢量演进——每条都在削弱这两个困难之一：\n\n| 矢量 | 演进 | 攻击的困难 | 实例 | 消除的痛点 |\n| --- | --- | --- | --- | --- |\n| 结构化 | 隐式 → 显式 | 时间不确定性 | Async/Await（控制流）、Structured Concurrency（生命周期） | 回调地狱、孤儿任务、资源泄漏 |\n| 去共享 | 共享 → 隔离/不可变 | 共享状态 | Actor、不可变数据（见核心矛盾） | 数据竞争 |\n| 静态化 | 运行时 → 编译期 | 时间不确定性 | Rust Ownership、会话类型（见两维坐标的右移） | 错误发现太晚 |\n| 无阻塞 | 挂起等待 → 流式推进 | 时间不确定性 | Lock-Free、Reactive 背压（见性能与伸缩性章） | 线程挂起传播、伸缩性瓶颈 |\n\n四条矢量殊途同归：要么**消除共享**，要么把**时间交错**变得显式、可证、不阻塞——与开篇\"共享 vs 隔离\"的核心矛盾首尾呼应。\n\n## 并发设计模式\n\n设计模式是前述原理的**落地实例**——\"问题 → 解法 → 代价\"的复用模板。三类模式分别对应三种诉求：**安全**（去共享，消除型控制）、**协调**（共享受限下的协作协议）、**伸缩**（突破单点容量）。每个模式都在转移而非消灭复杂度。\n\n### 安全性模式\n\n去共享 / 去可变，从根源消除竞争——\"消除型\"控制的实例。\n\n| 模式 | 解决的问题 | 机制 | 转移出的代价 |\n| --- | --- | --- | --- |\n| Immutable | 共享可变状态引发竞争 | 状态不可改，构造后永不迁移 | 每次\"修改\"需新建对象（内存 / GC 压力） |\n| Thread Confinement | 对象被多线程共享 | 对象限定在单一执行单元内，不发布 | 跨线程传递需显式拷贝或移交 |\n| Copy-On-Write | 读多写少时读写互斥开销大 | 写时复制副本，读旧本无锁 | 写放大、内存翻倍、读可能拿到旧快照 |\n| ThreadLocal | 全局状态被并发访问 | 每个执行单元持有私有副本 | 内存随线程数增长，线程池下需清理（泄漏 / 串数据） |\n\n### 协调性模式\n\n共享不可避免时，用结构化协议管理访问顺序——\"协调型\"控制的实例。\n\n| 模式 | 解决的问题 | 机制 | 转移出的代价 |\n| --- | --- | --- | --- |\n| Producer-Consumer | 生产 / 消费速率不匹配 | 队列缓冲，解耦两端节奏 | 队列容量与背压（满 / 空时阻塞） |\n| Guarded Suspension | 前置条件未满足时如何等待 | 条件不成立则挂起，成立再唤醒 | 虚假唤醒，须 while 循环复检 |\n| Reader-Writer | 读多写少时统一锁粒度过粗 | 读共享、写独占 | 写饥饿（读不断则写等不到） |\n| Two-Phase Termination | 如何安全停止运行中的任务 | 先发停止信号，再等清理完成 | 需可中断点，清理顺序敏感 |\n\n### 可伸缩模式\n\n突破单点容量与速率瓶颈——多在分布式层落地。\n\n| 模式 | 解决的问题 | 机制 | 转移出的代价 |\n| --- | --- | --- | --- |\n| Worker Pool | 无界任务并发导致资源耗尽 | 固定 worker 数 + 任务队列，复用执行单元 | 队列积压、拒绝策略，任务间不可相互依赖 |\n| MQ | 瞬时流量超过处理能力，上下游强耦合 | 异步消息缓冲，削峰填谷 + 解耦 | 延迟增加，消息重复 / 顺序 / 一致性 |\n| Sharding | 单点状态成为热点与容量瓶颈 | 按 key 拆分到多分片，并行处理 | 跨分片操作复杂，再平衡成本 |\n| Consistent Hash | 分片增减时数据大规模迁移 | 哈希环，节点变动只影响相邻区间 | 负载不均（需虚拟节点），实现复杂 |\n\n## 并发测试哲学\n\n### 根因：时间是不可控的隐藏输入\n\n普通测试是\"固定输入 → 固定输出\"；并发的输入除了数据，还有**交错顺序**，而它由运行时决定、每次不同（即前文的时间不确定性）。于是同样输入这次通过、下次崩溃——并发 Bug 时序相关、概率触发、难以复现。\n\n### 范式转变：从\"验证输出\"到\"探索交错\"\n\n既然时间是输入，测一次只覆盖了**一种交错**，等于只测了一个输入点。并发测试的核心因此转变：\n\n> 不是验证\"这次跑对了\"，而是**控制、扰动或穷尽交错空间**，逼出坏交错或证明其不存在。\n\n所有并发测试手段都是这一目标的不同强度实现。\n\n### 对策：两条路线\n\n| 路线 | 思路 | 手段 | 边界 |\n| --- | --- | --- | --- |\n| 提高触发概率 | 多跑、乱跑、扰动调度，让罕见坏交错显形 | 压力 / 随机重复、延迟注入（jcstress、CHESS）、竞争检测器（TSan、`-race`） | 只能\"发现存在\"，不能\"证明不存在\" |\n| 穷尽或证明 | 把交错空间系统化覆盖或形式化推理 | 确定性重放 / 模拟、模型检测（TLA+、SPIN）、不变式 / 属性断言 | 状态爆炸，规模受限 |\n\n竞争检测器是性价比最高的一档：它查的是**数据竞争这一根因**，不依赖 Bug 是否恰好显形。\n\n### 测试重点\n\n测什么，对应前文\"错误统一抽象\"的四类失效——关键是每一维如何在交错中检验：\n\n| 维度 | 核心 | 怎么测 |\n| --- | --- | --- |\n| 正确性 | 不变式始终成立 | 高并发下持续断言不变式（如余额 >= 0） |\n| 安全性 | 状态不被破坏 | 竞争检测器 + 随机交错压力 |\n| 活跃性 | 系统持续推进 | 死锁检测、超时探针、活锁观测（CPU 高但无进展） |\n| 性能 | 延迟与吞吐 | 递增并发压测，观察 ρ 趋近 1 时的拐点（见性能章） |\n\n## 并发误区与反模式\n\n### 认知误区\n\n观念层面的错误判断——多源于把直觉套用到并发：\n\n| 误区 | 真相 |\n| --- | --- |\n| 并发 = 并行（多线程必加速） | 并发管**等待**、并行才**加速**；CPU 密集的加速受 Amdahl 限制（见性能章） |\n| 锁 = 安全 | 锁只护它圈住的范围，跨多步的业务不变式仍可能被破坏（见错误抽象） |\n| volatile = 轻量锁 | volatile 只保证可见性 / 有序性，**不保证原子性**（见内存模型） |\n| 响应式无需同步 | 消除了显式回调，但 operator 间状态、订阅生命周期、线程切换边界仍需协调 |\n| 协程没有并发问题 | 单线程协程在 `await` 让出点仍会被交错 / 重入；多线程协程更叠加数据竞争 |\n| 死锁是偶然 | 死锁是结构缺陷——满足 Coffman 四条件就必然发生（见活跃性） |\n\n### 真正的反模式\n\n做法层面的坏实践——看似可行却有害：\n\n| 反模式 | 危害 | 正确做法 |\n| --- | --- | --- |\n| 忙等待 / 自旋空转 | 烧 CPU 却无进展 | 用条件变量 / 阻塞队列挂起等待 |\n| 锁内做 I/O 或调用外部代码 | 持锁时间不可控，利用率 ρ 飙升（见性能章） | I/O 移出临界区，锁内只护状态 |\n| 嵌套锁、加锁顺序不一致 | 循环等待 → 死锁 | 统一全局锁序 / 一次性获取 / tryLock 超时 |\n| 全局粗粒度锁 | 一切串行化，伸缩性归零 | 锁分段 / 缩小临界区 / 改无锁结构 |\n| 用 sleep 凑同步 | 既慢又不可靠，竞态依旧存在 | 显式同步原语（latch、条件变量） |\n| 双重检查锁定漏 volatile | 可能读到半初始化对象（见安全发布） | 字段加 volatile，或用静态 holder / 枚举单例 |\n\n## 并发设计哲学总结\n\n全文可收束为**一条因果链**：一个矛盾派生两类问题，两类问题对应两条对策，对策落地为各章内容。\n\n```text\n一个矛盾      共享状态 × 时间不确定性\n                ↓ 派生\n两类问题      安全性（状态协调失效） + 活跃性（进度协调失效）\n                ↓ 对策\n两条主线      消除共享          驯服时间\n              （隔离 / 不可变）   （结构化 / 静态化 / 无阻塞）\n                ↓ 落地\n各章展开      控制哲学 → 模型坐标 → 设计模式 → 测试范式\n```\n\n两条主线对应全文的两组章节：\n\n| 主线 | 攻击的困难 | 展开于 |\n| --- | --- | --- |\n| 消除共享 | 共享状态 | 控制哲学（消除型）、安全发布、安全性模式 |\n| 驯服时间 | 时间不确定性 | 内存模型（happens-before）、现代演化（结构化/静态化/无阻塞）、测试范式 |\n\n由此得到全文唯一的**最高原则**——按\"消除 > 协调\"排序：\n\n> 不共享 > 不可变 > 消息通信 > 乐观 > 互斥\n\n并发的真正难点不是线程、锁或 API，而是：\n\n> **如何在不确定时间中维持状态一致性。** 并发编程，本质上是\"状态协调工程学\"。\n\n## 关联内容\n\n- [/编程语言/并发模型.md](/编程语言/并发模型.md) 不同编程语言的并发模型比较，对应\"统一分类\"的坐标落地\n- [/编程语言/JAVA/JVM/JAVA内存模型.md](/编程语言/JAVA/JVM/JAVA内存模型.md) happens-before 与可见性/有序性/原子性在 JMM 中的具体实现\n- [/编程语言/Rust.md](/编程语言/Rust.md) 所有权与线性类型——\"静态约束\"轴的编译期并发安全\n- [/编程语言/编程范式/函数式编程.md](/编程语言/编程范式/函数式编程.md) 不可变性从根源消除并发问题，对应\"消除型\"控制\n- [/中间件/数据库/数据库系统/事务管理/事务.md](/中间件/数据库/数据库系统/事务管理/事务.md) MVCC、隔离级别、两阶段锁——乐观/悲观并发控制的数据库实现\n- [/操作系统/进程与线程.md](/操作系统/进程与线程.md) 操作系统层面的执行单元概念\n- [/操作系统/死锁.md](/操作系统/死锁.md) 死锁与 Coffman 条件，对应活跃性失效\n- [/计算机系统/程序结构和执行/存储器层次结构.md](/计算机系统/程序结构和执行/存储器层次结构.md) 缓存一致性、伪共享、局部性的硬件根因\n- [/软件工程/性能工程.md](/软件工程/性能工程.md) Amdahl 定律、USL、排队论——并发性能与伸缩性的理论基础\n- [/软件工程/架构/系统设计/高并发.md](/软件工程/架构/系统设计/高并发.md) 伸缩性原理在高并发系统设计中的应用\n- [/计算机网络/IO模型.md](/计算机网络/IO模型.md) IO 模型与异步/等待，关联 Async 与事件驱动并发","metadata":"tags: ['并发编程', '编程语言', '操作系统', '原理层']","hasMoreCommit":false,"totalCommits":2,"commitList":[{"date":"2026-06-03T21:13:17+08:00","author":"MY","message":"docs(并发编程): 重构并发编程文档结构和内容优化","hash":"9dd8f0de45864bb368e808e5e9627033fcb73dc8"},{"date":"2026-06-03T09:27:51+08:00","author":"MY","message":"docs(SUMMARY.md): add concurrent programming to language paradigms","hash":"82d7ae2c71cb4b02841e91b441bca66765a34751"}],"createTime":"2026-06-03T09:27:51+08:00"}