一個高效能無鎖非阻塞連結串列佇列

Tybyq發表於2018-11-05

這個是一個用c++ 11標準實現的無鎖非阻塞連結串列佇列,透過增加一個dummy節點,解偶合連結串列頭指標和尾指標。使得當只有一個生產者和一個消費者時,進隊和出隊都無需加鎖,進隊操作的是尾指標,出隊操作的是頭指標,互不干涉。對於多個生產者且單個消費者時,只需要對尾指標加鎖保護,而頭指標不需要加鎖。反之,對於單生產者且多消費者時,只需要對頭指標加鎖保護而尾指標不需要加鎖。如果是多生產者和多消費者,那麼頭尾指標各自加鎖保護。同時,佇列內部會對節點進行快取,避免重複的記憶體分配以提高效能。

在雙cpu的機器上測試,效能比boost實現的單生產者和單消費者佇列boost::lockfree::spsc_queue快6到7倍。

//對模板使用別名,方便使用(說明:NullMutex是一個空鎖,是一個自旋鎖spin_lock)

  //單生產者和單消費者
   template<typename VALUE_TYPE>  using  spsc_queue = TDoubleLockLinkedNonBlockingQueue<VALUE_TYPE, NullMutex, NullMutex>;

   //多生產者和單消費者
   template<typename VALUE_TYPE>  using  mpsc_queue = TDoubleLockLinkedNonBlockingQueue<VALUE_TYPE, spin_lock, NullMutex>;

   //單生產者和多消費者
   template<typename VALUE_TYPE>  using  spmc_queue = TDoubleLockLinkedNonBlockingQueue<VALUE_TYPE, NullMutex,spin_lock>;

   //多生產者和多消費者
   template<typename VALUE_TYPE>  using  mpmc_queue = TDoubleLockLinkedNonBlockingQueue<VALUE_TYPE, spin_lock, spin_lock>;

//使用例子:

//定義一個單生產者和單消費者佇列
spsc_queue<int> queue;
//進隊
queue.push(1);

//出隊
int value;
if(queue.pop(value))
{
   printf("value = %d \n",value);
}

下文測試例子在E5-2620 v3 雙cpu的機器上的執行結果:

////////////////////////////////////////////////////////////////////////////
單生產者[1]--單消費者[1]模型測試 資料請求[count=100000000]:

 NullMutex TDoubleLockLinkedNonBlockingQueue :  花時 3.010000 秒

 boost::lockfree::spsc_queue :  花時 19.312000 秒

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557424/viewspace-2218788/,如需轉載,請註明出處,否則將追究法律責任。

相關文章