{"name":"并发集合","id":"编程语言-JAVA-JAVA并发编程-并发集合","content":"# Java 并发集合：从实现细节到设计哲学\n\n> **并发问题模型 → 设计策略 → 具体实现** 的稳定知识体系。\n\n## 第一性原理：为什么需要并发集合？\n\n并发集合不是“线程安全的集合”这么简单，但也不是“根本矛盾的解决者”。准确定位它的角色，先要分清：哪些是问题、哪些是需求、哪个才是矛盾。\n\n### 四个并发关切，三种范畴\n\n普通集合面对的四个并发关切本不同范畴——混称“矛盾”会掩盖各自的可解性：\n\n| 并发关切  | 范畴     | 本质           | 可解性                |\n| ----- | ------ | ------------ | ------------------ |\n| 数据竞争  | 问题     | 多线程读写共享状态    | 有确定解：原子性 + 可见性      |\n| 线程协作  | 需求     | 生产者与消费者步调不一致 | 可满足：阻塞 / 唤醒 / 解耦    |\n| 顺序与时间 | 需求     | 有序性、延迟执行     | 可满足：时间语义表达         |\n| 读写冲突  | **矛盾** | 并发 ⇄ 一致性 / 性能 | **不可消解，只可取舍**      |\n\n前三者有解或可满足；唯有“读写冲突”是**本体张力**——遍历的“稳定视图”与“修改即时生效”不可兼得\n\n### 并发集合的角色：封装解，取舍矛盾\n\n消解性的手段不在集合层：原子与可见来自 JMM happens-before，原子变更来自 CAS，阻塞唤醒来自 park/unpark 与 Condition（见 [并发工具类.md](/编程语言/JAVA/JAVA并发编程/并发工具类.md)；JMM 与 CAS 原理见 [JAVA内存模型.md](/编程语言/JAVA/JVM/JAVA内存模型.md)）。并发集合只做两件事：\n\n* **封装**：把底层原语的现成解组合进数据结构，使用方无需直接触碰 CAS / 锁 / Condition\n* **取舍**：在不可消解的“并发 ⇄ 一致性”张力上，针对容器场景选定立场（弱一致 / 快照 / 写时复制）\n\n> 并发集合**承载并取舍**矛盾，而**不消解**矛盾——它不是并发问题的解的发明者，而是解的容器化封装与场景化取舍。\n\n## 并发集合的核心设计哲学\n\n### 一致性是取舍\n\n并发集合对“读取一致性”的全部处理，可归结为一根轴加一条分配律：一致性强度与并发度此消彼长，构成一根取舍轴；轴上的选点不按容器统一发放，而按操作粒度逐一计价。这根轴在**两个层次**上分别决策——先在容器级选立场，再在操作级分配强度（后者依赖前者，非平行维度）：\n\n| 层次 | 回答的问题 | 取值 | 支配律 |\n| --- | --- | --- | --- |\n| 容器级 | 读写并发时整体取哪种视图 | 禁止 / 中止 / 容纳 | 一致性 ⇄ 并发 不可兼得 |\n| 操作级 | 同一容器各操作给多强 | 单键强 / 聚合迭代弱 | 强度对齐同步成本 |\n\n分配律：**一致性强度按操作的代价分配**。单键读写已有 happens-before，强一致几乎没有额外的代价，于是给足；聚合（`size`）和迭代要强一致就得加全局锁，太贵，于是降级为弱一致换吞吐。这与「读优先假设」「最小共享原则」一脉相承——只在必要处付出协调成本。\n\n同一根取舍轴在单机与分布式上都成立：容器层的禁止 / 中止 / 容纳，对应分布式的线性 → 因果 → 最终一致，以及 CAP/PACELC 的一致性 ⇄ 可用性。。\n\n### 读优先假设\n\n大量并发容器默认假设：**读远多于写**\n\n之所以押注“读多写少”：读-读天然不冲突、同步成本只为冲突而付，故押注读占主导可把全部协调成本单边转嫁给稀疏的写、让高频读走无锁快路径，期望收益最大（边界：写频升高则此押注反噬）。\n\n由此演化出两条主线：\n\n* **读无锁 / 写加锁**（ConcurrentHashMap）\n* **写时复制，读快照**（CopyOnWriteArrayList）\n\n### 最小共享原则\n\n* 不共享，就不需要同步\n* 少共享，就降低锁竞争\n\n典型体现：\n\n* 分段锁 / 节点锁\n* putLock / takeLock 分离\n* CAS + 局部 synchronized\n\n> 并发容器的演进主线——锁粒度沿「全表锁 → 分段 → 节点锁 + CAS」单调收缩——正是「减少共享」这一通用规律在容器领域的投影。规律本身（消除型/协调型控制、共享面收缩、并发⇄一致性取舍、隔离→乐观→互斥的优先级）见 [并发编程.md](/编程语言/并发编程.md)「并发控制哲学 / 现代并发演化」。\n\n### 所有权转移而非共享\n\n转移所有权的价值在于走消除型控制——任一刻单一持有，竞态三要素中的\"并发访问\"被直接去除，对象因而免同步；这是「最小共享原则」推到极限（零共享）的形态。\n\n在队列模型中：\n\n* 对象不是“被多个线程共享”\n* 而是**在线程之间转移所有权**\n\n> 阻塞队列是一种串行线程封闭（Serial Thread Confinement）的实现形式。\n\n## 并发集合的分类：载体 × 灵魂\n\n```\n并发集合 = 载体（组织何种数据结构）× 灵魂（用何种策略消解竞态）\n```\n\n* **载体**：决定存取形态——选型的实践入口\n* **灵魂**：决定并发语义——认知的稳定主轴，跨语言、跨尺度不变\n\n### 载体轴：组织何种结构\n\n| 载体 | 存取形态 | 代表 |\n| --- | --- | --- |\n| Map | 键值映射 | `ConcurrentHashMap`、`ConcurrentSkipListMap`（有序） |\n| Set | 去重集合 | `ConcurrentSkipListSet`、`CopyOnWriteArraySet` |\n| List | 索引顺序表 | `CopyOnWriteArrayList` |\n| Queue | 单端进出 | `ConcurrentLinkedQueue`、`BlockingQueue` 族 |\n| Deque | 双端进出 | `ConcurrentLinkedDeque`、`LinkedBlockingDeque` |\n\n### 灵魂轴：用何种策略消解竞态\n\n竞态 = 共享 + 可变 + 并发访问，消解任一条即安全（见 [并发编程.md](/编程语言/并发编程.md) 消除型 / 协调型控制）。并发集合的安全策略按此分三类：\n\n| 策略 | 消解 | 范式 | 投影 |\n| --- | --- | --- | --- |\n| 不共享 | 去掉“共享”——所有权转移 | 串行线程封闭 | Queue 家族 |\n| 不可变 | 去掉“可变”——对读者冻结 | 快照 / 写时复制 | COW 系 |\n| 加秩序 | 管控“并发访问” | 乐观 CAS / 悲观锁分段 | CHM、SkipListMap、队列内部 |\n\n### 生成矩阵：用组合预测存在性\n\n载体 × 灵魂张成矩阵，空格本身即洞察：\n\n| 载体＼灵魂 | 加秩序（CAS/锁） | 不可变（COW） | 不共享（转移） |\n| --- | --- | --- | --- |\n| Map | CHM、SkipListMap | （罕见） | — |\n| List | （罕见，锁 List） | CopyOnWriteArrayList | — |\n| Set | SkipListSet | CopyOnWriteArraySet | — |\n| Queue | BlockingQueue 内部 | — | 本即转移语义 |\n\n空格不是在说明“这个组合为何不存在”：\n\n| 空格 | 缺席原因（即洞察） |\n| --- | --- |\n| 非 Queue × 不共享(转移) | 转移只对“流经的元素”成立；Map/List/Set 是驻留型容器，无所有权转移语义 → 转移是 Queue 专属 |\n| Map × 不可变(COW) 罕见 | Map 写按 key 局部更新，COW 须整表复制、写放大不可接受 → JDK 无 CopyOnWriteMap |\n| List × 加秩序 罕见 | List 随机写难以分段，锁分段收益低 → 读多写少 List 的需求被 COW 占据 |\n| Queue × 不可变(COW) | 队列元素不断进出，无“稳定迭代视图”需求 → COW 对队列不成立 |\n\n### 派生属性归位：现象 → 根因\n\n| 可观测现象 | 根因（哪个决策的投影） |\n| --- | --- |\n| 阻塞 / 非阻塞 | 载体 = Queue 且灵魂含 Condition 协作 |\n| 有界 / 无界 | Queue 的容量约束（流控需求） |\n| 聚合弱一致 | 灵魂 = 加秩序且无全局锁 的必然后果 |\n| 迭代快照一致 | 灵魂 = 不可变 / COW 的必然后果 |\n| 排序 / 延迟 | 载体 = 优先队列，延迟是按到期时间排序的特例 |\n\n## 设计策略层：容器如何复用原语\n\n> 原语本身——CAS、锁与公平性、park/Condition——的原理在 [/编程语言/JAVA/JVM/JAVA内存模型.md](/编程语言/JAVA/JVM/JAVA内存模型.md) 与 [/编程语言/JAVA/JAVA并发编程/并发工具类.md](/编程语言/JAVA/JAVA并发编程/并发工具类.md)。本章只看容器特有的增量：把通用原语**贴合到数据结构上**的复用技术。三族灵魂各对应一组。\n\n### 加秩序：把锁粒度贴合结构\n\n容器的增量是**让协调成本随结构分布**，而非锁住整体：\n\n| 容器化技术 | 机制 | 代表 |\n| --- | --- | --- |\n| 分段 / 节点锁 | 锁粒度 = 单桶 / 单节点，竞争被散列打散 | `ConcurrentHashMap` |\n| 双锁分离 | 队头队尾各一把锁，入队与出队互不阻塞 | `LinkedBlockingQueue`（putLock/takeLock） |\n| CAS 无锁链表 | 入队出队仅 CAS 头尾指针，零锁 | `ConcurrentLinkedQueue` |\n| 扩容协作 | 多线程并发迁移桶，迁移期读写不停 | `ConcurrentHashMap` resize |\n\n> 这些是「最小共享原则」的落地：锁粒度沿「全表 → 分段 → 节点 + CAS」单调收缩。\n\n### 不可变：写时复制\n\n容器特有，无对应 JUC 工具——核心是把“对读者冻结”做成机制：\n\n* 写：复制 → 改副本 → 替换引用（替换点加锁串行化）\n* 读：直读当前引用指向的快照，**零同步**\n\n> 读到的恒是某次替换的完整快照——迭代天然一致、不抛 CME。代价是写放大与内存翻倍，故前提是写少读多。本质是“以空间换无锁读”。\n\n### 不共享：所有权转移的协作点\n\n容器把阻塞 / 唤醒原语封装为**队满则等、队空则等**的节流阀，put/take 即所有权交接点——机制已在「所有权转移」节阐明，实现细节见 BlockingQueue 族。\n\n## 并发容器选型方法论\n\n### 先问问题，而不是选类\n\n* 是否需要阻塞？\n* 是否需要限流？\n* 读多还是写多？\n* 是否有时间语义？\n\n### 决策表：场景 → 实例\n\n| 场景特征 | 推荐 |\n| --- | --- |\n| 高并发读写 Map | `ConcurrentHashMap` |\n| 需有序 / 范围查询的 Map | `ConcurrentSkipListMap` |\n| 读极多写极少 List | `CopyOnWriteArrayList` |\n| 高并发非阻塞队列 | `ConcurrentLinkedQueue` |\n| 阻塞 / 限流 / 交接 / 调度 | `BlockingQueue` 族（见下「容量轴」） |\n\n### 代价对照：失效模式即选用边界\n\n| 实例 | 载体 × 灵魂 | 核心代价 / 失效模式 |\n| --- | --- | --- |\n| `ConcurrentHashMap` | Map × 加秩序 | `size`/聚合弱一致，仅供估算 |\n| `ConcurrentSkipListMap` | 有序 Map × 加秩序 | 单点 O(log n) vs O(1) |\n| `CopyOnWriteArrayList` | List × 不可变 | 写放大 + 内存翻倍，写 O(n) |\n| `ConcurrentLinkedQueue` | Queue × 不共享(CAS) | 无阻塞语义、`size()` O(n)、无界有 OOM 风险 |\n\n### BlockingQueue：容量轴即协作语义\n\n家族的第一区分轴是**容量**，容量值直接映射协作语义，其余差异（单 / 双锁）是该轴的实现派生：\n\n| 容量 | 实例 | 协作语义 | 触发场景 | 代价 / 失效模式 |\n| --- | --- | --- | --- | --- |\n| 0 | `SynchronousQueue` | 直接交接，无缓冲 | 线程间一对一移交 | 无消费者时 `offer` 立即失败、`put` 阻塞 |\n| 有界固定 | `ArrayBlockingQueue` | 背压限流 | 严格流控 | 满则生产者阻塞 / 拒绝；容量预分配 |\n| 可选（默认无界） | `LinkedBlockingQueue` | 缓冲削峰 | 流量波动 | 默认无界 → OOM 风险（同 `ConcurrentLinkedQueue`） |\n| 时间 / 优先序 | `DelayQueue`、`PriorityBlockingQueue` | 按到期 / 优先级出队 | 定时调度 | 仅到期元素可取，`poll` 可能返回 null 即便非空；无界 → OOM |\n\n> 容量 0 → 交接、有限 → 限流、无限 → 缓冲——一根轴解释整个家族的存在理由。\n\n## 并发集合的终极认知\n\n并发集合不发明并发的解，只在两根轴上做**场景化取舍**——*如何消解竞态* 与 *一致性给到多强*。这两轴跨语言、跨单机与分布式不变；记轴，而非类名。\n\n| 稳定洞察 | 内核 | 跨尺度同构 |\n| --- | --- | --- |\n| 安全策略由竞态决定 | 竞态三要素（共享 / 可变 / 并发访问）→ 三族策略（不共享 / 不可变 / 加秩序），即消除型 vs 协调型 | 锁、事务、分布式并发控制同此三分 |\n| 一致性是取舍轴 | 强度按成本分配——廉价处给足、昂贵处降级 | 分布式 线性 → 因果 → 最终一致、CAP / PACELC |\n| 代价是策略的影子 | 选定灵魂即选定代价：不可变必写放大、无锁聚合必弱一致 | 任何乐观 / 复制方案的固有税 |\n| 转移即孤岛 | 所有权转移 = 共享内存模型里的一座消息传递孤岛 | Actor 邮箱、Go channel、CSP |\n\n> 两轴生成全部容器：**竞态消解策略 × 一致性取舍点**。其余一切——阻塞、有界、有序、乃至类名——都是这两轴在具体载体上的投影。\n\n## 关联内容（自动生成）\n\n- [/编程语言/JAVA/JAVA并发编程/并发工具类.md](/编程语言/JAVA/JAVA并发编程/并发工具类.md) 提供 CAS、锁、Condition 等原语，并发集合是其在数据结构上的封装；二者构成“原语—容器”分工\n- [/编程语言/并发编程.md](/编程语言/并发编程.md) 消除型/协调型控制与共享面收缩等通用规律，是“灵魂轴三族”的上位母题\n- [/编程语言/并发模型.md](/编程语言/并发模型.md) 所有权转移即共享内存模型中的“消息传递孤岛”，与 Actor、CSP、channel 同解一题\n- [/软件工程/架构/系统设计/分布式/分布式理论.md](/软件工程/架构/系统设计/分布式/分布式理论.md) 一致性按成本分配的取舍轴，同构于分布式 CAP/PACELC 与线性→因果→最终一致谱系\n- [/中间件/数据库/数据库系统/事务管理/事务.md](/中间件/数据库/数据库系统/事务管理/事务.md) 弱一致/快照取舍同构于数据库 MVCC 与乐观并发控制（版本号+事后校验）\n- [/编程语言/JAVA/JAVA并发编程/Disruptor.md](/编程语言/JAVA/JAVA并发编程/Disruptor.md) 无锁环形缓冲队列，是 BlockingQueue 家族在高吞吐场景的高性能替代\n- [/编程语言/JAVA/JAVA并发编程/线程池.md](/编程语言/JAVA/JAVA并发编程/线程池.md) 线程池以 BlockingQueue 为任务缓冲，是并发集合最典型的协作场景\n- [/编程语言/JAVA/JAVA并发编程/线程.md](/编程语言/JAVA/JAVA并发编程/线程.md) 并发集合的协作与所有权转移建立在线程生命周期与状态转换之上\n- [/编程语言/JAVA/高级/集合/集合.md](/编程语言/JAVA/高级/集合/集合.md) 并发集合是普通集合的线程安全扩展，理解普通集合是前提\n- [/软件工程/架构/系统设计/高并发.md](/软件工程/架构/系统设计/高并发.md) 高并发系统中并发集合是多线程数据共享与性能优化的核心工具\n- [/编程语言/JAVA/JAVA并发编程/JAVA并发编程.md](/编程语言/JAVA/JAVA并发编程/JAVA并发编程.md) 并发集合在 Java 并发编程整体体系中的定位\n","metadata":"tags: ['并发编程', '编程语言', '数据结构', '设计模式', '架构设计']","hasMoreCommit":true,"totalCommits":12,"commitList":[{"date":"2026-06-25T21:22:50+08:00","author":"MY","message":"refactor(java并发): 退役 基础概念.md，三处增量迁入权威篇","hash":"cc9e3a8038d179371125a1151bb670322796c083"},{"date":"2026-06-19T12:03:26+08:00","author":"MY","message":"feat(java): 重构并发集合文档完善设计哲学和分类体系","hash":"1d73e04b348225ddb707db706c20a81adc80fe82"},{"date":"2026-02-12T14:07:03+08:00","author":"MY","message":"doc: 整理标签","hash":"290b3e8ad18f48832ac282290238d020fc030a88"},{"date":"2026-01-08T11:52:55+08:00","author":"MY","message":"doc(java-collections): 重构文档","hash":"e0203004013ac1a831e58f218e6acaca027ed080"},{"date":"2025-12-30T10:23:34+08:00","author":"MY","message":"docs(JAVA): 重构并发集合文档结构并完善设计哲学说明","hash":"9072e0e393f3d273a4a2196cb3ae6f64ca235fde"},{"date":"2024-06-05T14:47:56+08:00","author":"MY","message":"✏并发","hash":"7c6ef9e57ea5c46ce3933e394560d07213d85163"},{"date":"2022-07-13T14:09:29+08:00","author":"cjiping","message":"✏️更新 定时算法","hash":"9e2f23d2d92e2e8257b36b252f33c3674d3e8889"},{"date":"2022-03-09T17:46:16+08:00","author":"cjiping","message":"✏️更新 JAVA并发编程","hash":"05cdd8647ade510badf68feae84d459e83c2b943"},{"date":"2022-03-08T17:09:17+08:00","author":"cjiping","message":"✏️更新 并发集合","hash":"e7031296c5eadfe32c6710f21b31544b9529bba8"},{"date":"2022-02-22T09:45:42+08:00","author":"cjiping","message":"✏️更新 并发集合","hash":"a6091a622f9000d1291c65e2996c2dc54b61772c"}],"createTime":"2020-07-02T12:35:05+08:00"}