c++无锁链表的实现
生活随笔
收集整理的這篇文章主要介紹了
c++无锁链表的实现
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
簡(jiǎn)言
1.無(wú)鎖能夠?qū)崿F(xiàn)的核心原理即CAS
2. c++語(yǔ)言中CAS一般有三種操作,即gcc的CAS實(shí)現(xiàn),windows的CAS實(shí)現(xiàn),c++11的CAS實(shí)現(xiàn)
3. 這篇博客主要講c++11的CAS實(shí)現(xiàn)
4. 具體原理分析可參考:https://blog.csdn.net/yzf279533105/article/details/119798571
實(shí)驗(yàn)過(guò)程
1. 預(yù)先加入10000個(gè)節(jié)點(diǎn),加上一個(gè)空節(jié)點(diǎn),一共10001個(gè)節(jié)點(diǎn)
2. 開(kāi)500個(gè)線程增加10萬(wàn)節(jié)點(diǎn),同時(shí)開(kāi)500個(gè)線程刪除10萬(wàn)節(jié)點(diǎn)
3. 打印鏈表長(zhǎng)度,發(fā)現(xiàn)仍然是10001
實(shí)驗(yàn)如下圖
完整代碼
#include <iostream> #include <atomic> #include <thread> #include <unistd.h> #include <stdlib.h>using namespace std;// 節(jié)點(diǎn) struct Node {int value;atomic<Node*> next; };// 無(wú)鎖鏈表 struct NoLockList {atomic<Node*> pHead;atomic<Node*> pTail;void enqueueOne(int thread, int n, bool stop); // 入隊(duì)int dequeueOne(int thread, bool stop); // 出隊(duì)void enqueueMany(int thread, int m, bool stop); // 入隊(duì)多個(gè)節(jié)點(diǎn)void dequeueMany(int thread, int m, bool stop); // 出隊(duì)多個(gè)節(jié)點(diǎn)int len(); // 長(zhǎng)度 };// 壓入隊(duì)列一個(gè)節(jié)點(diǎn) void NoLockList::enqueueOne(int thread, int n, bool stop) {// 新建節(jié)點(diǎn)Node* pnew = new Node();pnew->value = n;pnew->next = NULL;Node* ptail = NULL;Node* ptailnext = NULL;Node* pNULL = NULL;while (true){ptail = pTail; // 每次拿隊(duì)列最新的Tailptailnext = pTail.load()->next;// 若pTail不是真正鏈表末尾,則后移pTail// 注意此步不可簡(jiǎn)單地continue,因?yàn)槠渌€程可能因?yàn)槟撤N原因?qū)е轮患尤肓诵鹿?jié)點(diǎn),未能更新Tail指針,這里可以修正if (ptailnext != NULL){pTail.compare_exchange_weak(ptail, ptailnext);cout<<"enqueueOne::ptailnext != NULL, thread="<<thread<<endl;continue;}if (stop){usleep(500+rand()%500);}// 核心:若pTail->next為空,則確定pTail是鏈表尾節(jié)點(diǎn),則pTail->next改為指向新節(jié)點(diǎn),修改失敗則重試if (pTail.load()->next.compare_exchange_weak(pNULL, pnew)){// 更新尾指針pTail,即使更新失敗也沒(méi)關(guān)系,說(shuō)明其他線程已經(jīng)更新了pTailpTail.compare_exchange_weak(ptail, pnew);cout<<"enqueueOne,suc, thread="<<thread<<endl;return;}cout<<"enqueueOne::retry"<<endl;} }// 出隊(duì)列 int NoLockList::dequeueOne(int thread, bool stop) {Node* phead = NULL;Node* ptail = NULL;Node* pheadNext = NULL;while (true){phead = pHead;ptail = pTail;pheadNext = phead->next;// 鏈表為空(只有一個(gè)初始節(jié)點(diǎn))if (pheadNext==NULL){cout<<"dequeueOne::pheadNext==NULL"<<endl;return -1;}// 鏈表不為空,但pHead指針和pTail相等,說(shuō)明pTail未能及時(shí)更新,則后移pTailif (phead == ptail){cout<<"dequeueOne::phead == ptail, thread="<<thread<<endl;pTail.compare_exchange_weak(ptail,pheadNext);continue;}// 隨機(jī)暫停一段時(shí)間if (stop){usleep(500+rand()%500);}// 核心:若pList->pHead確定是鏈表頭部節(jié)點(diǎn),則后移Head;失敗則重試if ( pHead.compare_exchange_weak(phead, pheadNext)){int val = phead->value;free(phead);cout<<"dequeueOne,suc, thread="<<thread<<endl;return val;}cout<<"dequeueOne::retry, thread="<<thread<<endl;} }// 入隊(duì)多個(gè)節(jié)點(diǎn) void NoLockList::enqueueMany(int thread, int m, bool stop) {for (int i=0;i<m;i++){enqueueOne(thread, i,stop);} }// 出隊(duì)多個(gè)節(jié)點(diǎn) void NoLockList::dequeueMany(int thread, int m, bool stop ) {for (int i=0;i<m;i++){dequeueOne(thread, stop);} }// 隊(duì)列長(zhǎng)度 int NoLockList::len() {if (pHead.load() == pTail.load()){return 1;}int le = 1;Node* p = pHead;while (p->next.load()){p = p->next.load();le++;}return le; }int main() {NoLockList list;// 初始化第一個(gè)空節(jié)點(diǎn)Node* pNew = new Node();pNew->value = 0;pNew->next = NULL;list.pHead = pNew;list.pTail = pNew;// 10萬(wàn)個(gè)節(jié)點(diǎn)const int nodeNum = 100000;// 1000個(gè)線程const int threadNum = 1000;// 初始10000節(jié)點(diǎn)for (int i=0;i<10000;i++){list.enqueueOne(0, i,false);}cout<<"start, list elements is : "<<list.len()<<endl;// 多個(gè)線程進(jìn)行入隊(duì),出隊(duì)操作thread en[threadNum];thread de[threadNum];for (int i=0;i<threadNum;i++){en[i] = thread(&NoLockList::enqueueMany, &list, i, nodeNum/threadNum,true);de[i] = thread(&NoLockList::dequeueMany, &list, i, nodeNum/threadNum,true);}for (int i=0;i<threadNum;i++){de[i].join();en[i].join();}cout<<"end, list elements is : "<<list.len()<<endl;return 0; }總結(jié)
以上是生活随笔為你收集整理的c++无锁链表的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 无锁链表的c++实现
- 下一篇: QT隐式调用VC开发的DLL