日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SkipList和java中ConcurrentSkipListMap的实现

發(fā)布時間:2024/2/28 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SkipList和java中ConcurrentSkipListMap的实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 簡介
  • SkipList
  • ConcurrentSkipListMap
    • SkipList的實現(xiàn)
    • concurrent的實現(xiàn)
  • 總結(jié)

SkipList和java中ConcurrentSkipListMap的實現(xiàn)

簡介

一開始聽說SkipList我是一臉懵逼的,啥?還有SkipList?這個是什么玩意。

后面經(jīng)過我的不斷搜索和學習,終于明白了SkipList原來是一種數(shù)據(jù)結(jié)構(gòu),而java中的ConcurrentSkipListMap和ConcurrentSkipListSet就是這種結(jié)構(gòu)的實現(xiàn)。

接下來就讓我們一步一步的揭開SkipList和ConcurrentSkipListMap的面紗吧。

SkipList

先看下維基百科中SkipList的定義:

SkipList是一種層級結(jié)構(gòu)。最底層的是排序過的最原始的linked list。

往上是一層一層的層級結(jié)構(gòu),每個底層節(jié)點按照一定的概率出現(xiàn)在上一層list中。這個概率叫做p,通常p取1/2或者1/4。

先設(shè)定一個函數(shù)f,可以隨機產(chǎn)生0和1這兩個數(shù),并且這兩個數(shù)出現(xiàn)的幾率是一樣的,那么這時候的p就是1/2。

對每個節(jié)點,我們這樣操作:

我們運行一次f,當f=1時,我們將該節(jié)點插入到上層layer的list中去。當f=0時,不插入。

舉個例子,上圖中的list中有10個排序過的節(jié)點,第一個節(jié)點默認每層都有。對于第二個節(jié)點,運行f=0,不插入。對于第三個節(jié)點,運行f=1,將第三個節(jié)點插入layer 1,以此類推,最后得到的layer 1 list中的節(jié)點有:1,3,4,6,9。

然后我們再繼續(xù)往上構(gòu)建layer。 最終得到上圖的SkipList。

通過使用SkipList,我們構(gòu)建了多個List,包含不同的排序過的節(jié)點,從而提升List的查找效率。

我們通過下圖能有一個更清晰的認識:

每次的查找都是從最頂層開始,因為最頂層的節(jié)點數(shù)最少,如果要查找的節(jié)點在list中的兩個節(jié)點中間,則向下移一層繼續(xù)查找,最終找到最底層要插入的位置,插入節(jié)點,然后再次調(diào)用概率函數(shù)f,決定是否向上復(fù)制節(jié)點。

其本質(zhì)上相當于二分法查找,其查找的時間復(fù)雜度是O(logn)。

ConcurrentSkipListMap

ConcurrentSkipListMap是一個并發(fā)的SkipList,那么它具有兩個特點,SkipList和concurrent。我們分別來講解。

SkipList的實現(xiàn)

上面講解了SkipList的數(shù)據(jù)結(jié)構(gòu),接下來看下ConcurrentSkipListMap是怎么實現(xiàn)這個skipList的:

ConcurrentSkipListMap中有三種結(jié)構(gòu),base nodes,Head nodes和index nodes。

base nodes組成了有序的鏈表結(jié)構(gòu),是ConcurrentSkipListMap的最底層實現(xiàn)。

static final class Node<K,V> {final K key;volatile Object value;volatile Node<K,V> next;/*** Creates a new regular node.*/Node(K key, Object value, Node<K,V> next) {this.key = key;this.value = value;this.next = next;}}

上面可以看到每個Node都是一個k,v的entry,并且其有一個next指向下一個節(jié)點。

index nodes是構(gòu)建SkipList上層結(jié)構(gòu)的基本節(jié)點:

static class Index<K,V> {final Node<K,V> node;final Index<K,V> down;volatile Index<K,V> right;/*** Creates index node with given values.*/Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) {this.node = node;this.down = down;this.right = right;}}

從上面的構(gòu)造我們可以看到,Index節(jié)點包含了Node節(jié)點,除此之外,Index還有兩個指針,一個指向同一個layer的下一個節(jié)點,一個指向下一層layer的節(jié)點。

這樣的結(jié)構(gòu)可以方便遍歷的實現(xiàn)。

最后看一下HeadIndex,HeadIndex代表的是Head節(jié)點:

static final class HeadIndex<K,V> extends Index<K,V> {final int level;HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right, int level) {super(node, down, right);this.level = level;}}

HeadIndex和Index很類似,只不過多了一個level字段,表示所在的層級。

在ConcurrentSkipListMap初始化的時候,會初始化HeadIndex:

head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),null, null, 1);

我們可以看到HeadIndex中的Node是key=null,value=BASE_HEADER的虛擬節(jié)點。初始的level=1。

concurrent的實現(xiàn)

接下來,我們再看一下并發(fā)是怎么實現(xiàn)的:

基本上并發(fā)類都是通過UNSAFE.compareAndSwapObject來實現(xiàn)的,ConcurrentSkipListMap也不例外。

假如我們有三個節(jié)點,b-n-f。現(xiàn)在需要刪除節(jié)點n。

第一步,使用CAS將n的valu的值從non-null設(shè)置為null。這個時候,任何外部的操作都會認為這個節(jié)點是不存在的。但是那些內(nèi)部的插入或者刪除操作還是會繼續(xù)修改n的next指針。

第二步,使用CAS將n的next指針指向一個新的marker節(jié)點,從這個時候開始,n的next指針將不會指向任何其他的節(jié)點。

我們看下marker節(jié)點的定義:

Node(Node<K,V> next) {this.key = null;this.value = this;this.next = next;}

我們可以看到marker節(jié)點實際上是一個key為null,value是自己的節(jié)點。

第三步,使用CAS將b的next指針指向f。從這一步起,n節(jié)點不會再被其他的程序訪問,這意味著n可以被垃圾回收了。

我們思考一下為什么要插入一個marker節(jié)點,這是因為我們在刪除的時候,需要告訴所有的線程,節(jié)點n準備被刪除了,因為n本來就指向f節(jié)點,這個時候需要一個中間節(jié)點來表示這個準備刪除的狀態(tài)。

總結(jié)

本文從SkipList數(shù)據(jù)結(jié)構(gòu)開始,講解了ConcurrentSkipListMap的實現(xiàn)。希望大家能夠喜歡。

更多精彩內(nèi)容且看:

  • 區(qū)塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續(xù)更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續(xù)更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續(xù)更新
  • java程序員從小工到專家成神之路(2020版)-持續(xù)更新中,附詳細文章教程

歡迎關(guān)注我的公眾號:程序那些事,更多精彩等著您!
更多內(nèi)容請訪問:flydean的博客

總結(jié)

以上是生活随笔為你收集整理的SkipList和java中ConcurrentSkipListMap的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。