無鎖佇列的原理與實現
阿新 • • 發佈:2019-02-05
最近幾天在思考無鎖佇列,看了相關文章,也讀了一些部落格,最後寫了一份程式碼,程式碼實現對在多執行緒環境下對佇列的讀和寫是不需要加鎖的。程式碼如下所示:
#include <windows.h> #pragma comment(lib, "Kernel32.lib") template<typename VT> class LcFQue{//lock free queue public: struct QueNode{ QueNode *next; VT value; }; public: LcFQue(); ~LcFQue(); public: void EnQue(const VT& val); VT DeQue(); private: QueNode *tail; QueNode *head; }; template<typename VT> LcFQue<VT>::LcFQue(){ tail= head= new QueNode; tail->value= -1; tail->next= NULL; } template<typename VT> LcFQue<VT>::~LcFQue(){ QueNode* DelNode= head; while(DelNode!= tail){ head= head->next; delete DelNode; DelNode= head; } delete DelNode; } template<typename VT> void LcFQue<VT>::EnQue(const VT& val){ QueNode* node = new QueNode; node->next = NULL; node->value = val; QueNode* tTail; do{ tTail= tail; }while(InterlockedCompareExchange((LONG*)&(tTail->next),(LONG)node,NULL)!= NULL); InterlockedCompareExchange((LONG*)(&tail),(LONG)node,(LONG)tTail); } template<typename VT> VT LcFQue<VT>::DeQue(){ QueNode* tHead; do{ tHead= head; if(tHead->next==NULL){ return -1; } }while(InterlockedCompareExchange((LONG*)(&head),(LONG)(head->next),(LONG)tHead)!= (LONG)tHead); return tHead->next->value; } #include <stdlib.h> #include <string.h> #include <iostream> #include <ctime> #include <cstdlib> using namespace std; LcFQue<int> que; int C[1000]; DWORD WINAPI EnQue(void* ParAddr); DWORD WINAPI Deque(void* ParAddr); int main(){ memset(C,0,sizeof(C)); srand(time(NULL)); HANDLE hThread[10]; int AddEd[10]; for(int i= 0; i< 10; ++i){ AddEd[i]= i; } LPTHREAD_START_ROUTINE func; for(int i= 0; i< 10; ++i){ if(i> 5){ func= Deque; }else{ func= EnQue; } hThread[i]= ::CreateThread( NULL, 0, func, AddEd+i, 0, NULL ); } ::WaitForMultipleObjects(10,hThread,TRUE,INFINITE); } DWORD WINAPI Deque(void* ParAddr){ while(true){ ::Sleep(10); int val= que.DeQue(); if(val==-1){ continue; } cout<<val<<'\n'; ++C[val]; } return 0; } DWORD WINAPI EnQue(void* ParAddr){ int* obj= (int*)ParAddr; for(int i= 0; i< 100; ++i){ que.EnQue(i*5+*obj); ::Sleep(rand()%10); } return 0; }