栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ConcurrentSkipListMap java中的跳跃表

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ConcurrentSkipListMap java中的跳跃表

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

Index

HeadIndex

跳表结构

跳表的查找


表查找有一个很重要的方法 private Node findPredecessor(Object key, Comparator 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某些处理并发的操作。以后补救


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/356159.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号