concurrentskiplistmap底层查找本质是“从上往下、从左往右”的多层链表遍历:从最高层头节点开始,每层向右滑动至next.key≥target.key时下降,直至level 0确认存在性,全程无锁、无递归、纯指针游走,平均o(log n)。

ConcurrentSkipListMap 的底层查找,本质是“从上往下、从左往右”的多层链表遍历,不依赖锁,也不走树形递归,靠的是跳表结构天然的分层索引能力。
查找从最高层头节点开始
跳表不是单层链表,而是由若干层(level)组成的有序链表堆叠。查找时,JVM 会先定位到最高层的头索引节点(HeadIndex),然后在这个层级上向右推进,只要下一个节点的 key 小于目标 key,就继续前进;一旦遇到 next.key ≥ target.key,就停止横向移动,准备下降。
- 每层都是严格升序的单向链表,所有层共享同一套 key 排序逻辑
- 最高层节点最少,跨度最大,起“粗筛”作用;越往下节点越密,精度越高
- 层数不是固定值,而是动态增长的,取决于插入时的随机 level 决定
逐层下降直到命中或触达底层
当某一层无法再向右跳过时,就向下落到下一层,重复“向右滑动 → 判断大小 → 停止或下降”的过程。这个动作持续到 Level 0(最底层),也就是包含全部键值对的完整有序链表。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- Level 0 是唯一保证包含所有元素的层,所以最终结果一定在这里判定
- 如果在 Level 0 找到 key 相等的节点,返回对应 value;否则说明键不存在
- 整个过程没有回溯、无递归、无阻塞,纯指针游走,平均只需 log₂(n) 次比较
volatile + CAS 支持并发中的一致性读取
虽然查找本身不修改结构,但 ConcurrentSkipListMap 允许多线程同时读写。为确保查找线程能看到其他线程刚插入/删除的节点,所有关键字段(如 Node.next、Index.right)都声明为 volatile。
- volatile 保证每次读取都是最新值,避免线程本地缓存导致的“看不见新节点”问题
- CAS 不参与查找流程,但它保障了插入/删除过程中指针更新的原子性,间接让查找始终面对一个结构上“自洽”的跳表
- 即使某个节点正处于被逻辑删除(value = null)的过程中,查找仍能安全跳过它,不会 NPE 或崩溃
为什么能支持高效范围查询?
因为底层就是按 key 排好序的链表,查找路径天然具备顺序性。subMap、headMap 等视图不是拷贝数据,而是复用原有节点指针,直接从某个位置开始沿 Level 0 链表往后/往前遍历。
- 迭代器走的是实际 next 指针,不是 hash 散列后重排,所以顺序稳定
- 逆序遍历也成立——跳表结构本身支持双向索引(虽 Java 实现只用单向,但通过辅助结构可推导前驱)
- 不需要额外排序或构建临时集合,开销远低于先 dump 再 sort
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










