2026/3/29 9:53:35
网站建设
项目流程
礼品网站实例,怎么制作小程序软件,运营推广计划表,网站制作价格行情一、整体定位#xff1a;它是什么#xff1f;ConcurrentSkipListMap 是一个 可扩展、线程安全、按键排序的并发 Map#xff0c;实现了 ConcurrentNavigableMap 接口。底层数据结构#xff1a;跳表#xff08;Skip List#xff09;#xff0c;而非红黑树#xff08;如 T…一、整体定位它是什么ConcurrentSkipListMap是一个可扩展、线程安全、按键排序的并发 Map实现了ConcurrentNavigableMap接口。底层数据结构跳表Skip List而非红黑树如TreeMap。排序方式支持自然排序Comparable或自定义Comparator。并发模型无锁Lock-Free通过CASCompare-And-Swap实现线程安全。作者Doug LeaJava 并发包之父。引入版本JDK 1.6。✅适用场景需要高并发读写 键有序 范围查询如 subMap, headMap的场景例如高频交易系统中的订单簿按价格排序缓存淘汰策略如 LRU 有序分布式系统中的有序任务队列二、为什么用“跳表”而不是“红黑树”这是 Doug Lea 在注释中明确解释的关键设计选择❝There are no known efficient lock-free insertion and deletion algorithms for search trees.❞对比分析特性红黑树TreeMap跳表ConcurrentSkipListMap单线程性能O(log n)常数因子小O(log n)常数因子略大并发实现难度极难实现无锁需复杂指针操作天然适合无锁链表 指针 CAS实现复杂度高旋转、平衡中概率性结构逻辑清晰内存局部性差树节点分散较好链表连续跳表索引缓存友好范围遍历支持支持且正向更快✅结论在高并发无锁场景下跳表比平衡树更容易实现、更稳定、更可预测。三、核心并发机制如何做到线程安全1.双层删除标记Two-Phase Deletion这是最关键的无锁删除算法避免 ABA 问题和中间状态不一致。删除一个节点n前驱b后继f分三步初始: ... → [b] → [n] → [f] → ... Step 1: 将 n.value 设为 null逻辑删除 → 所有 get/containsKey 都认为 n 不存在 Step 2: 在 n 后插入一个 marker 节点 ... → [b] → [n] → [marker] → [f] → ... → 阻止其他线程在 n 后插入新节点 Step 3: CAS b.next 跳过 [n] 和 [marker] ... → [b] → [f] → ... → 物理删除完成n 可被 GC✅优势其他线程在遍历时若发现value null会主动“帮助”完成删除helpDelete避免阻塞。使用普通Node作为 markervalue this节省空间避免AtomicMarkedReference的开销。2.值为 null 表示逻辑删除正常节点value是实际值非 null已删除节点value nullMarker 节点value this自引用 这与Map.get(key)返回null表示“不存在”完美契合无需额外标记。3.索引层Index Levels独立维护基础层base level存储所有键值对用上述无锁链表。索引层index levels多层“快速通道”每层是基础层的子集。索引插入/删除是惰性的先完成基础层操作再异步更新索引。减少 CAS 冲突窗口避免索引节点内存泄漏确保删除后索引不可达 跳表高度动态调整插入时可能提升层级删除时可能降低启发式。4.弱一致性迭代器Weakly Consistent Iterators迭代器不会抛出ConcurrentModificationException能看到调用 iterator() 之前已存在的元素可能看到、也可能看不到并发修改的元素不会重复遍历同一元素✅ 适合高并发读多写少场景牺牲强一致性换取高性能。四、重要注意事项来自 Javadoc特性说明size()不是 O(1)需遍历所有元素结果可能是近似值遍历时被修改不支持null键/值因get(key)返回null表示“不存在”无法区分Entry.setValue()不支持返回的Map.Entry是快照需用replace()修改批量操作非原子putAll,clear,equals等不是原子操作正向遍历更快升序ascending比降序descending性能更好五、性能与空间时间复杂度get,put,remove,containsKey平均O(log n)空间开销约 25% 节点有索引p0.5总空间略小于TreeMap并发性能远优于Collections.synchronizedMap(new TreeMap())六、总结如何理解这段代码ConcurrentSkipListMap是 Doug Lea 利用“跳表 无锁链表 双阶段删除 弱一致性”设计出的一个高性能并发有序 Map。它牺牲了部分强一致性如 size() 不精确、迭代器弱一致换来了极高的并发吞吐量和可扩展性是高并发场景下替代TreeMap的首选。关键创新点用普通 Node 实现删除标记避免 AtomicMarkedReference 开销逻辑删除valuenull与物理删除分离支持高效并发索引层惰性更新减少竞争防止内存泄漏帮助机制helpDelete让其他线程协助完成删除避免阻塞。类比记忆想象一条高速公路基础链表上面每隔一段就有立交桥索引层。当你要拆除一个出口删除节点先挂“施工中”牌子valuenull再建个临时隔离带marker最后把路直接接过去CAS 跳过。其他司机线程看到施工牌会主动帮你清理现场helpDelete这就是ConcurrentSkipListMap的智慧。