ConcurrentSkipListMap java中的跳跃表

因为要学习Redis接触到跳表,看不懂C就来看看Doug Lea大神实现的跳表,鉴于外面的很多跳表图,偷懒画得不完整。我手动画一个

Node

在这里插入图片描述

Index

在这里插入图片描述

HeadIndex

在这里插入图片描述

跳表结构

在这里插入图片描述

跳表的查找

在这里插入图片描述
表查找有一个很重要的方法 private Node<K,V> findPredecessor(Object key, Comparator<? super K> cmp) ,通过比较器和给定的key 找到前驱节点。我们先看看该方法
在这里插入图片描述

第一步 循环开始前

在这里插入图片描述
此时表格的状态
在这里插入图片描述

第二步 如果r 不等于 null。如上图所示 r不等于 null,我们看看

在这里插入图片描述
在这里插入图片描述
我们知道现在 r 节点存在 其 node的key值为 3 ,通过compare比较发现比 5小 ,5 大于 3 ,cpr(cmp, key, k) 返回值结果大于 0,然后 q = r , r = r.right,continue;
在这里插入图片描述
循环继续,我们不难发现 r 还是不等于 null ,其 node 的 key 值 为 6 。cpr(cmp, key, k) 返回值结果小于 0,跳出循环,到了
在这里插入图片描述
d = q. down 不等于 null ,所以暂时不走 return 。走 q = d , r = d.right,结果图如下。

在这里插入图片描述
此时循环继续,下面我们加快,r 的 node 的 key值 4 小于 5 所以 ,变成如下图
在这里插入图片描述
然后 现在 r 的 node 的 key 值大于 5,但是 此时 q.down = null,所以返回前驱节点 4
在这里插入图片描述
findPredecessor大致流产我们讲完了,接下来查找节点

doGet

在这里插入图片描述
很简单的单向链表操作,应该不需要多讲。

跳表的添加 doPut

在这里插入图片描述
doput 也会调用 查找前驱节点的方法,也就是找到了节点 4.
我们从节点 4 开始 看接下来的代码
在这里插入图片描述

第一步 循环开始前

在这里插入图片描述
分别让 b指向 前驱节点,n指向 b.next , f 指向 n.next; 显然我们的 n 不为null。

第二步 前面还有一些并发下处理我们先不管,走主要流程在这里插入图片描述

如果 n 的key比 要参入的key 要小,那么就继续前进。显然我们现在 n 的 key 为 5,参入 key 的值 为4.5 , c < 0;

第三部 插入该节点

在这里插入图片描述
创建新的节点,把新节点指向 n,通过casNext操作把 b.next指向 新的节点。cas失败,返回false 取反 结果为 true,break 内部循环,重新添加 节点 4.5.
在这里插入图片描述

第四部 随机数建立 Index节点

在这里插入图片描述
rnd 与上 0x80000001(16进制) = rnd 与上(二进制) 1000 0000 0000 0000 0000 0000 0000 0001
在这里插入图片描述
其结果为0,也就是说 rnd 第 31 位 和 第 0 位 值必须为 0,概率为 四分之一。我们假设随机为 0xxx xxxx xxxx xxxx xxxx xxxx xx01 1110
在这里插入图片描述
在这里插入图片描述
0xxx xxxx xxxx xxxx xxxx xxxx xx01 1110 有连续 4个1,也就是 level 等级 为 5;
在这里插入图片描述
如图我们的等级只有2,明显小于5,也就是走到第二步。

创建index 节点链表,level = max + 1 = 2 + 1
在这里插入图片描述
在这里插入图片描述
创建了如上图所示的index链表,你可以想成在纵向方向上,已经建立好了关系,接下来需要处理横向的关系。因为我们的创建 level 是 max + 1 ,从图中我们也看出来了 ,比原来高出一层,下面的代码就是创建一个新的headIndex,并切换head标志位
在这里插入图片描述

在这里插入图片描述
循环开始前,建立状态

在这里插入图片描述
在这里插入图片描述

看图我们知道 r 不等于 null 执行下面的代码
在这里插入图片描述
跟之前一样,比较key ,前移,因为一开始是相等的,所以第一次 c == 0。如果不相等的话,那么就前移,直到找到n节点的key大于 参入节点,或者 n节点为 null。下一部操作
在这里插入图片描述
回到上面图,我们知道 j == insertionLevel 都等于 3。再次连接该节点(为什么说再次,因为最新一层,在一开始就已经建立好关系,但是为了代码工整,冗余一下代码),连接代码很简单不用解释了把,也就断开关系,连接上
在这里插入图片描述
如果在还有得情况下,那么就 insertionLevel–, j–。直到操作完全部的 index连接。

操作完成后,跳表

在这里插入图片描述
在如上状态下,结束index链表参入,并且因为数组是局部变量,会自动清除。所以不需要管理

删除节点

在这里插入图片描述
已删除4.5节点为例,一下是准备删除时候的状态。
在这里插入图片描述
在这里插入图片描述
首先把n节点的值变为null,接着追上一个标志节点,同时把b的next指向 f
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
unlink方法很简单,就是把前驱点解指向 当前节点 后继节点。

至此ConcurrentSkipListMap已经学习完毕,但还是存在一些疑惑,Doug Lea某些处理并发的操作。以后补救

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值