国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

世界上最簡(jiǎn)單的無(wú)鎖哈希表

開(kāi)發(fā) 后端
無(wú)鎖哈希表(Lock-Free Hash Table )可以提高多線程下的性能表現(xiàn),但是因?yàn)閷?shí)現(xiàn)一個(gè)無(wú)鎖哈希表本身的復(fù)雜度不小。

無(wú)鎖哈希表(Lock-Free Hash Table )可以提高多線程下的性能表現(xiàn),但是因?yàn)閷?shí)現(xiàn)一個(gè)無(wú)鎖哈希表本身的復(fù)雜度不小。(ps:真正的復(fù)雜在于出錯(cuò)之后的調(diào)試,因?yàn)槎嗑€程下的調(diào)試本身就很復(fù)雜,引入無(wú)鎖數(shù)據(jù)結(jié)構(gòu)之后,傳統(tǒng)的看堆棧信息和打印log都基本上沒(méi)有意義了。堆棧中的數(shù)據(jù)可能被并發(fā)訪問(wèn)破壞,而打印log本身可能會(huì)改變程序執(zhí)行時(shí)對(duì)數(shù)據(jù)訪問(wèn)的時(shí)序。一個(gè)比較可行的做法是實(shí)現(xiàn)一個(gè)無(wú)鎖版本和一個(gè)傳統(tǒng)數(shù)據(jù)結(jié)構(gòu)+鎖的版本,出錯(cuò)后通過(guò)替換來(lái)定位是無(wú)鎖數(shù)據(jù)結(jié)構(gòu)本身的bug還是其他邏輯的 bug)。所以對(duì)一個(gè)項(xiàng)目而言,無(wú)鎖數(shù)據(jù)結(jié)構(gòu)基本上是一把雙刃劍。

據(jù)我所知,***個(gè)用于實(shí)際開(kāi)發(fā)的無(wú)鎖哈希表是 Dr. Cliff Click 為Java而寫。在2007年他發(fā)布了這個(gè)無(wú)鎖哈希表的源碼并且在google做了關(guān)于它的報(bào)告(視頻)。我承認(rèn),在我***次看這個(gè)報(bào)告的時(shí)候,我對(duì)它的大部分內(nèi)容都不理解。Dr. Cliff Click是這個(gè)領(lǐng)域的先驅(qū)。(Maged M. Michael 在IBM做了大量關(guān)于無(wú)鎖數(shù)據(jù)結(jié)構(gòu)的研究。這個(gè)是2002年的一篇論文,關(guān)于哈希表,http://www.research.ibm.com/people/m/michael/spaa-2002.pdf)

很幸運(yùn),6年時(shí)間足夠我理解Dr. Cliff Click所做的研究。事實(shí)上,你不必做一些前沿的探索,去實(shí)現(xiàn)一個(gè)***的無(wú)鎖哈希表。在這里我將分享我實(shí)現(xiàn)的這個(gè)版本。我相信有使用C++進(jìn)行多線程開(kāi)發(fā)經(jīng)驗(yàn)的程序員,可以通過(guò)這篇博客梳理以前的經(jīng)驗(yàn),并且完全理解它。

約束

作為一個(gè)程序員,平時(shí)我們實(shí)現(xiàn)一個(gè)數(shù)據(jù)結(jié)構(gòu)會(huì)本能的盡可能通用。這不是一件壞事,但是當(dāng)我們把通用當(dāng)作一個(gè)更重要的目標(biāo)時(shí),它可能會(huì)阻礙我們。在這里我走向另一個(gè)極端,實(shí)現(xiàn)了一個(gè)盡可能簡(jiǎn)單的,僅用于一些特殊環(huán)境的哈希表,下面是它的設(shè)計(jì)約束:

  1. table 只接受類型為32位整數(shù)的key和value

  2. 所有key必須非零

  3. 所有的value必須非零

  4. table的***數(shù)目固定且必須是2的冪

  5. 唯一可用的操作是SetItem和getItem

  6. 有沒(méi)有刪除操作

當(dāng)然你掌握了這種算法實(shí)現(xiàn)機(jī)制之后,可以在此基礎(chǔ)上進(jìn)行擴(kuò)展,而不受這些限制的約束。(rehash,刪除和遍歷,這些都會(huì)增加復(fù)雜度,而且有引發(fā)新的ABA問(wèn)題的可能性)。

實(shí)現(xiàn)方法

有很多種方法來(lái)實(shí)現(xiàn)一個(gè)哈希表。這里我選擇了用我以前的帖子中描述的ArrayOfItems類做一個(gè)簡(jiǎn)單的修改,(前置擴(kuò)展閱讀) A Lock-Free… Linear Search?

這個(gè)哈希表被我稱為HashTable1,和ArrayOfItems一樣,它采用了一個(gè)巨大的key-value pairs數(shù)組實(shí)現(xiàn)。

  1. struct Entry  
  2. {  
  3.     mint_atomic32_t key;  
  4.     mint_atomic32_t value;  
  5. };  
  6. Entry *m_entries;  

在hashtable1中,僅僅只有數(shù)組本身而沒(méi)有使用鏈接來(lái)處理碰撞。數(shù)組全部初始化為0,key為0時(shí)對(duì)應(yīng)的節(jié)點(diǎn)為空。插入時(shí),會(huì)通過(guò)線性搜索找到一個(gè)空節(jié)點(diǎn)。

ArrayOfItems和HashTable1之間唯一的區(qū)別是,ArrayOfItems是從0開(kāi)始做線性搜索,而HashTable1使用MurmurHash3′s integer finalizer算法得到一個(gè)hash值,然后以這個(gè)hash值為起點(diǎn)開(kāi)始搜索()

  1. inline static uint32_t integerHash(uint32_t h) 
  2.     h ^= h >> 16; 
  3.     h *= 0x85ebca6b; 
  4.     h ^= h >> 13; 
  5.     h *= 0xc2b2ae35; 
  6.     h ^= h >> 16; 
  7.     return h; 

當(dāng)我們使用相同的key做參數(shù)調(diào)用SetItem或GetItem方法時(shí),它會(huì)在相同的index開(kāi)始做線性搜索,而使用不同的key時(shí),會(huì)在不同的 index開(kāi)始搜索。通過(guò)這種方式,可以提高查找到對(duì)應(yīng)key所在節(jié)點(diǎn)的速度,并且保證多線程并發(fā)調(diào)用SetItem或GetItem的安全性。

HashTable1采用環(huán)形的搜索,當(dāng)搜索到尾部時(shí),會(huì)從數(shù)組頭部開(kāi)始繼續(xù)搜索。在數(shù)組滿之前,每次搜索都可以保證返回對(duì)應(yīng)key所在的節(jié)點(diǎn),或者是一個(gè)空節(jié)點(diǎn)。這種技巧被稱為open addressing with linear probing,,在我看來(lái)這無(wú)疑是對(duì)lock-free最友好的hash算法,事實(shí)上在Dr. Cliff Click為java實(shí)現(xiàn)的哈希表中也使用了相同的技巧。

 

代碼

SetItem的實(shí)現(xiàn)。它會(huì)掃描整個(gè)數(shù)組并且將value保存在與key對(duì)應(yīng)的節(jié)點(diǎn)或空節(jié)點(diǎn)。這段代碼與ArrayOfItems:: SetItem幾乎相同,唯一的區(qū)別是計(jì)算了hash值并且按位與,保證index在數(shù)組邊界內(nèi)。

  1. void HashTable1::SetItem(uint32_t key, uint32_t value) 
  2.     for (uint32_t idx = integerHash(key);; idx++) 
  3.     { 
  4.         idx &= m_arraySize - 1; 
  5.   
  6.         uint32_t prevKey = mint_compare_exchange_strong_32_relaxed(&m_entries[idx].key, 0, key); 
  7.         if ((prevKey == 0) || (prevKey == key)) 
  8.         { 
  9.             mint_store_32_relaxed(&m_entries[idx].value, value); 
  10.             return
  11.         } 
  12.     } 

GetItem的實(shí)現(xiàn)也同樣和ArrayOfItems::GetItem有類似的改變。

  1. uint32_t HashTable1::GetItem(uint32_t key) 
  2.     for (uint32_t idx = integerHash(key);; idx++) 
  3.     { 
  4.         idx &= m_arraySize - 1; 
  5.   
  6.         uint32_t probedKey = mint_load_32_relaxed(&m_entries[idx].key); 
  7.         if (probedKey == key) 
  8.             return mint_load_32_relaxed(&m_entries[idx].value); 
  9.         if (probedKey == 0) 
  10.             return 0;          
  11.     } 

上述功能都是線程安全的,無(wú)鎖的ArrayOfItems出于同樣的原因:對(duì)數(shù)組的元素采用原子操作,使用cas操作修改節(jié)點(diǎn)的key值(使用內(nèi)存柵障保證線程安全,事實(shí)上就是重新排列了內(nèi)存訪問(wèn)指令的執(zhí)行次序)。在上一篇中有更詳細(xì)的討論。

***,就像在以前的帖子中,我們可以優(yōu)化SetItem,***次判斷是否可以避免使用CAS操作。如下這種優(yōu)化,可以使示例應(yīng)用程序運(yùn)行快大約20%。

  1. void HashTable1::SetItem(uint32_t key, uint32_t value) 
  2.     for (uint32_t idx = integerHash(key);; idx++) 
  3.     { 
  4.         idx &= m_arraySize - 1; 
  5.   
  6.         // Load the key that was there. 
  7.         uint32_t probedKey = mint_load_32_relaxed(&m_entries[idx].key); 
  8.         if (probedKey != key) 
  9.         { 
  10.             // The entry was either free, or contains another key. 
  11.             if (probedKey != 0) 
  12.                 continue;           // Usually, it contains another key. Keep probing. 
  13.                   
  14.             // The entry was free. Now let's try to take it using a CAS. 
  15.             uint32_t prevKey = mint_compare_exchange_strong_32_relaxed(&m_entries[idx].key, 0, key); 
  16.             if ((prevKey != 0) && (prevKey != key)) 
  17.                 continue;       // Another thread just stole it from underneath us. 
  18.   
  19.             // Either we just added the key, or another thread did. 
  20.         } 
  21.           
  22.         // Store the value in this array entry. 
  23.         mint_store_32_relaxed(&m_entries[idx].value, value); 
  24.         return
  25.     } 

這個(gè)就是幾乎可以精簡(jiǎn)的最簡(jiǎn)單的無(wú)鎖哈希表,這里是它的代碼鏈接: source and header。

一個(gè)忠告:與ArrayOfItems一樣,HashTable1上的所有操作都采用了relaxed memory ordering做限制。因此,當(dāng)在HashTable1中設(shè)置標(biāo)記,共享一些數(shù)據(jù)供其他線程訪問(wèn)時(shí),必須事先插入release fence。同樣訪問(wèn)數(shù)據(jù)的線程在調(diào)用GetItem前需要acquire fence。

  1. // Shared variables 
  2. char message[256]; 
  3. HashTable1 collection; 
  4.   
  5. void PublishMessage() 
  6.     // Write to shared memory non-atomically. 
  7.     strcpy(message, "I pity the fool!"); 
  8.       
  9.     // Release fence: The only way to safely pass non-atomic data between threads using Mintomic. 
  10.     mint_thread_fence_release(); 
  11.       
  12.     // Set a flag to indicate to other threads that the message is ready. 
  13.     collection.SetItem(SHARED_FLAG_KEY, 1) 

簡(jiǎn)單樣例

對(duì)HashTable1的一些測(cè)試對(duì)比,在上一篇帖子我做個(gè)一個(gè)類似的測(cè)試。它交替執(zhí)行2個(gè)測(cè)試:一個(gè)采用2個(gè)線程,每個(gè)線程交替插入6000個(gè)key不同的item,另一個(gè)每個(gè)線程交替插入12000個(gè)key相同但是value不同的item。

 

代碼放在GitHub上,你可以自己編譯和執(zhí)行。編譯說(shuō)明見(jiàn)README.md

在HashTable1沒(méi)有滿時(shí)—少于80%時(shí)—HashTable1表現(xiàn)的很好,我也許應(yīng)該為這個(gè)說(shuō)法做一些基準(zhǔn)測(cè)試。但是以以往的常規(guī)的哈希表 作為基準(zhǔn),我敢肯定你很難實(shí)現(xiàn)出性能更好的無(wú)鎖哈希表。這似乎奇怪,HashTable1基于ArrayOfItems,看起來(lái)會(huì)很低效。當(dāng)然,任何哈希 表中,總會(huì)有發(fā)生碰撞的風(fēng)險(xiǎn),而降階到ArrayOfItems的風(fēng)險(xiǎn)并不為0。但是使用一個(gè)足夠大的數(shù)組和類似MurmurHash3這樣的hash函 數(shù),這種情況出現(xiàn)的很少。

在實(shí)際的工作中,我已經(jīng)使用了一個(gè)和這個(gè)類似的hash-table。這是一個(gè)游戲開(kāi)發(fā)的項(xiàng)目,我的工作是解決使用內(nèi)存分配跟蹤工具(memory tracker)之后對(duì)一個(gè)讀寫鎖激烈的爭(zhēng)用。遷移到無(wú)鎖哈希表的過(guò)程非常棘手。相對(duì)HashTable1需要更復(fù)雜的數(shù)據(jù)結(jié)構(gòu),key和value都是 指針而不是簡(jiǎn)單的整數(shù)。因此有必要在哈希表內(nèi)部插入memory ordering。最終在此模式下運(yùn)行:最壞情況下游戲的幀率提高了4-10 FPS。

原文鏈接:http://preshing.com/20130605/the-worlds-simplest-lock-free-hash-table

譯文鏈接:http://blog.jobbole.com/39186/

責(zé)任編輯:陳四芳 來(lái)源: 伯樂(lè)在線
相關(guān)推薦

2018-11-06 12:22:18

排序算法代碼

2014-09-05 09:08:58

2010-09-02 13:21:46

2025-03-27 00:45:00

2013-04-24 09:57:08

Excel微軟

2023-07-31 08:59:46

軟件FossilSQLite

2025-03-13 00:35:00

2015-11-25 09:41:05

數(shù)據(jù)中心

2014-02-11 09:58:19

環(huán)保數(shù)據(jù)中心泰坦

2013-07-09 10:11:41

程序設(shè)計(jì)大賽程序員

2025-11-11 02:55:00

OracleJavaScriptES5

2024-10-14 10:58:13

2025-10-10 03:00:00

2024-01-11 09:11:08

數(shù)據(jù)庫(kù)SQLite管理

2025-01-09 11:10:15

2024-07-15 09:06:51

2018-07-19 19:07:33

語(yǔ)言編程語(yǔ)言程序

2013-05-08 09:38:28

InteropNetSDN網(wǎng)絡(luò)設(shè)備供應(yīng)商

2018-12-04 15:46:53

編程語(yǔ)言Python

2009-09-11 10:41:36

數(shù)據(jù)中心
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

欧美日本一道本在线视频| 日韩精品在线观看av| 久色乳综合思思在线视频| 日本a口亚洲| 制服丝袜中文字幕亚洲| 黑粗硬长欧美在线视频免费的| 国产真实精品久久二三区| 欧美日韩最好看的视频| 欧美日韩在线二区| 国内精品伊人久久| 国产亚洲欧美日韩一区二区| 黄网站app在线观看大全免费视频| 国产91精品一区二区麻豆亚洲| 鬼打鬼之黄金道士1992林正英| 国产精品99视频| 欧洲亚洲女同hd| 日韩精品视频中文字幕| 亚洲男人天天操| 偷拍精品精品一区二区三区| 精品国产凹凸成av人导航| 黄色片在线看| 欧美日本一区二区在线观看| 在线观看av网站永久| 亚洲欧美欧美一区二区三区| 成人精品视频一区二区| 国产婷婷精品av在线| 日韩欧美在线播放视频| 成人国产在线观看| 久久这里只有精品23| 国产精品一卡二卡| 婷婷视频在线播放| 香蕉久久a毛片| 青青草久久网络| 亚洲男女自偷自拍| 日本一区二区精品视频| 国产成人午夜99999| 久久精品无码中文字幕| 成人国产视频在线观看| 乱妇乱女熟妇熟女网站| 久久久99精品免费观看| 天堂网在线免费观看| 综合在线观看色| 黄色在线网站| 欧美一区二区三区影视| 羞羞的视频在线观看| 精品中文字幕久久久久久| 欧美不卡高清一区二区三区| 久久影视电视剧免费网站| 国产成人高清| 99re视频在线观看| 亚洲在线视频| 丰满少妇被猛烈进入高清播放| 99久久久久免费精品国产| 亚洲免费看av| 亚洲国产成人tv| 伦xxxx在线| 日韩激情在线视频| 6080成人| yellow视频在线观看一区二区| 性高湖久久久久久久久| 日韩av黄色网址| 亚洲精品你懂的| 在线观看的av| 亚洲精品美女在线观看| 日韩视频在线直播| 国产精品久久久久久久久久东京| 香蕉视频国产精品 | 日韩精品免费一区二区三区| 久久精品ww人人做人人爽| 日韩二区三区在线观看| www.在线观看av| 国产欧美日韩在线观看视频| 色视频一区二区三区| 久久嫩草精品久久久精品| 免费观看一二区视频网站| 色综合天天综合给合国产| 超黄网站在线观看| 久久久午夜视频| 亚洲一级在线| 制服丝袜影音| 正在播放亚洲一区| 色成人综合网| 欧洲av一区| 国产一区日韩二区欧美三区| 日本桃色视频| 亚洲精选一区二区| 欧美最新另类人妖| 亚洲一区三区视频在线观看| 国产精品午夜免费| 一级毛片在线看| 国模一区二区三区私拍视频| 国产香蕉久久精品综合网| 九九热免费精品视频| 精品国产乱码久久久久久蜜臀| 成人综合网站| 国产精品6699| 国内精品伊人久久久久av一坑 | 国产导航在线| 丝袜情趣国产精品| 欧美黄免费看| 欧美日韩中文在线视频| 亚洲变态欧美另类捆绑| 九九免费精品视频在线观看| 一级一片免费播放| 美女写真理伦片在线看| 99视频免费观看蜜桃视频| 国产欧美精品一区aⅴ影院| 成熟了的熟妇毛茸茸| 亚洲蜜桃精久久久久久久| 麻豆tv入口在线看| 国产极品精品在线观看| 久久精品二区亚洲w码| 最近中文字幕mv2018在线高清| 久久久www成人免费精品| 99成人免费视频| h精品动漫在线观看| 久久69精品久久久久久国产越南| 日韩国产欧美视频| 国产在线视频网| 91精品久久久久久久久久久久久久 | 中文无码久久精品| 1024欧美极品| 97精品国产97久久久久久免费| 97aⅴ精品视频一二三区| 69av成人| 日韩一区二区三区高清| 欧美无人高清视频在线观看| 国产一区二区三区四区三区四 | 欧美精品二区三区四区免费看视频| 一道本成人在线| 亚洲欧美亚洲| 不卡在线视频| 欧美日韩精品免费在线观看视频| 日韩一卡二卡三卡四卡| 日韩精品一级二级| 免费在线小视频| 国产又粗又猛又爽又黄的网站| 亚洲无av在线中文字幕| 国产传媒久久文化传媒| 国产福利91精品一区二区| 少妇高潮毛片色欲ava片| 久久中文久久字幕| 中文字幕一区二区在线观看 | 成人高清在线视频| 亚洲欧洲一二区| 成人拍拍拍在线观看| 国产精品pans私拍| 黄网站色欧美视频| 亚洲国产日韩在线| 成人18在线| 日本美女久久| 欧美v亚洲v| 在线观看爽视频| 不卡一卡2卡3卡4卡精品在| 国产日韩成人精品| 久久91精品| 亚洲伦理在线| 日韩资源av在线| 中文字幕最新精品| 亚洲丝袜精品丝袜在线| 欧美精品导航| 日本免费久久| xxx国产在线观看| 成人有码在线播放| 精品国产伦一区二区三区免费| gogo大胆日本视频一区| 久久爱www成人| 国产一级二级三级在线观看| 色播亚洲婷婷| 久久国产精品视频| 欧美性极品xxxx做受| 久久99久久99精品免视看婷婷| 爱情电影网av一区二区| 精品女厕厕露p撒尿| 亚洲精品视频一区二区三区| 久久这里有精品视频| 精品国产电影一区| 国产九色精品成人porny| 啄木系列成人av电影| 国产三区在线观看| 手机看片福利日韩| 精品欧美国产一区二区三区不卡| 在线观看亚洲区| 岛国av一区二区| 美女网站在线免费欧美精品| 日韩aaa久久蜜桃av| 中文字幕有码在线观看| www.99在线| 欧美在线播放一区| 日韩av电影在线网| 国产丝袜高跟一区| 欧美日韩亚洲天堂| 成人av在线观| 欧美日本一区二区高清播放视频| 欧美美女被草| 好操啊在线观看免费视频| 男人的天堂www| 黄色片免费在线观看视频| 国产伦精品一区二区三区照片| 久久久久久久色|