BASE_HEADER节点
指向ConcurrentSkipListMap里左下角位置的节点。
索引节点 index
index中的node属性,指向的就是最下面的node节点。
down属性和right属性,指向的是下面和右边的index节点,如果下面没有index(就是node节点)down是null,同理右边没有index,right是null。(构造方法里参数顺序是node,down,right)
索引头 headIndex
headIndex继承了index,只是增加了level属性,表示当前的索引列表在第几层。
可以理解成每一条索引链表的头节点。Level有下到上是递增的。每个index的level是随机获取的。
怎么保证由上而下每个索引链表上的index结点数量是递增的呢?因为每个index节点都会由上而下down属性延伸到最底层的node链表上,这样就保证了上一层的index节点,下面所有的level都会有相同的index节点。
ConcurrentSkipListMap里head属性,指向的就是最上面的headIndex节点。
插入操作doPut
findPredecessor方法找到要插入key的前继节点b,和后继节点n(也就是原来b的后继节点),由此看出ConcurrentSkipListMap是排序好的集合。
调用casNext(),通过cas方式插入node。
通过随机算法获取该节点index的level,如果是新level,生成新的headIndex。(level是顺序递增的,不会随机跳跃)
根据level遍历该level的index链表,找到合适的位置插入index结点,之后为下面几层都插入index节点?当然right节点也会更新。
删除操作remove(因为是无锁操作,凡是别的线程并发处理不一致的情况,基本都是break里面的for循环重来。)
-
先找到要删除节点n的前继节点b(因为真正删除的时候是更新前继节点b的next)
-
检查完前继节点,后继节点等后,对n节点casValue(n.value, null)。
-
appendMarker(node)标记节点方法,表示在this后面追加一个node,这个node和普通节点没有区别,只是标记用。标记节点的作用在于,保证了并发时候插入操作的结果。因为插入是通过casNext(oldNode,newNode)方法,会先compare oldNode,再做swap。所以原节点后已经插入了标记节点后,另一个线程要在原节点后插入新节点是失败的。
-
下一步删除就比较简单了,假设要删除的节点是n,前继节点是b,标记节点是f,删除的动作就是b.next = f.next。
网友评论