欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c++實現(xiàn)LinkBlockedQueue的問題

 更新時間:2020年10月26日 09:24:36   作者:封fenghl  
這篇文章主要介紹了c++實現(xiàn)LinkBlockedQueue的問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

c++鏈表實現(xiàn)的阻塞隊列

最近從java源碼里發(fā)現(xiàn)了阻塞隊列的實現(xiàn),覺得非常有趣。

首先,介紹下什么是阻塞隊列。阻塞隊列代表著一個隊列可以線程安全的往該隊列中寫數(shù)據(jù)和從該隊列中讀數(shù)據(jù)。也就是說,我們可以在多個線程之間并發(fā)的進行寫數(shù)據(jù)和讀數(shù)據(jù),而不會引發(fā)任何并發(fā)問題。

下面我們就說說如何實現(xiàn)一個阻塞隊列。

而實現(xiàn)一個阻塞隊列的前提:

  1. 需要能夠使用鏈表實現(xiàn)一個隊列
  2. 能夠使用c++的鎖機制,去給隊列的寫和讀操作加鎖。

為了性能,這里的讀和寫的鎖不能是同一把鎖。而對于一個鏈表隊列來說,讀取操作肯定需要涉及頭指針,寫操作肯定涉及尾指針。既然要實現(xiàn)讀操作一把鎖和寫操作一把鎖。那么就要求讀操作只能更改頭指針而不能更改尾指針,寫操作只能更改尾指針而不能更改頭指針。不滿足這個要求,那么讀寫操作就不可能實現(xiàn)用兩把鎖分別對讀寫進行加鎖。

基本隊列的實現(xiàn)

現(xiàn)在我們先說說如何實現(xiàn)這個隊列。

要求:入隊操作(enqueue)只能操作尾指針(last), 出隊操作(dequeue)只能操作頭指針(head)。

對于隊列的初始化,這里不能單純的設(shè)置為空指針,需要將頭尾指針同一節(jié)點。

下面我們來看入隊操作如何實現(xiàn)

從這個入隊操作來看,該操作只更改了尾指針last, 而沒有更改頭指針head。

其代碼實現(xiàn)為:

 void enqueue(int item) {
    Node *node = new Node(item);
    last = last->next = node;
  }

接下來我們來看出隊操作如何實現(xiàn)

從出隊操作來看就有趣的多,它拋棄了head所指向的節(jié)點,而這個節(jié)點有可能是那些節(jié)點呢?

  • 初始化時所賦值的那個節(jié)點
  • 出隊后的節(jié)點

也就是說,head所指向的節(jié)點中的val值沒有任何實際含義。當需要出隊時,出隊head指向的下一個節(jié)點first中val的值,然后拋棄head本身指向的值,讓head指向head的下一個節(jié)點first,此時head原來所指向的節(jié)點將被刪除?,F(xiàn)在我們可以看出出隊操作也只改變了頭指針head的值。

其代碼實現(xiàn)為:

 int dequeue() {
    Node *h = head;
    Node *first = head->next;
    delete h;
    head = first;
    int x = first->item;
    return x;
  }

現(xiàn)在隊列已經(jīng)實現(xiàn),下面就看看阻塞隊列如何實現(xiàn)。

阻塞隊列的實現(xiàn)

既然是阻塞隊列,那就意味這加鎖和等待。那就需要對c++的一些鎖知識和條件變量有了解。

先來看看我們需要實現(xiàn)阻塞隊列的那些方法:

Special Value Blocks Times out
Insert offer(o) put(o) offer(o,timeout)
Remove poll() take() poll(timeout)

入隊

讓我們先來實現(xiàn)put這個方法。

先看其實現(xiàn)流程圖:

由于該隊列實現(xiàn)有最大值限制,故在插入數(shù)據(jù)之前需要先判斷該隊列是否已滿,已滿則需等待該隊列有可用空間。在該線程入隊操作完成后,可能有別的線程也在等待入隊,需要喚醒其他寫數(shù)據(jù)的線程,使其繼續(xù)執(zhí)行后續(xù)操作。如果入隊前隊列為空,可能有出隊操作正在阻塞等待讀數(shù),也需要去喚醒讀數(shù)據(jù)的線程。

在看代碼實現(xiàn)之前,我們需要定義一些變量用于代碼實現(xiàn)環(huán)節(jié):

 /* The capacity bound*/
  int64_t capacity;
  /*Current number of elements */
  std::atomic<int64_t> count;  
	/** Lock held by take, pool, etc */
  std::mutex takeLock;
  /** Wait queue for waiting takes */
  std::condition_variable notEmpty;
  /** Lock held by put, offer, etc */
  std::mutex putLock;
  /** Wait queue for waiting puts */
  std::condition_variable notFull;

put函數(shù)的代碼實現(xiàn):

void LinkedBlockingQueue::put(const int item){
  int c;
  {
    std::unique_lock<std::mutex> lck{putLock};
    if( count == capacity) {
      notFull.wait(lck, [this](){return count < capacity;}); //(1)
    }
    enqueue(item); //不應(yīng)該把申請空間放在鎖里面,耗時有點大
    c = count.fetch_add(1);
  }
  if(c + 1 < capacity) {
    notFull.notify_one();
  }

  if(0 == c) {
    notEmpty.notify_one();
  }
}

對于offer(o)的實現(xiàn),主要更改是對上述代碼(1)中的等待改為直接返回false, 表示,當前沒有可用空間插入數(shù)據(jù)。正常插入就返回true.

對于offer(o,timeout)的實現(xiàn),就需要在上述代碼(1)中的wait函數(shù)添加上時間參數(shù),使其可以在timeout時間內(nèi)返回,如果是正常喚醒,正常入隊,則返回ture,否則返回false.

該更改為:

 if(!notFull.wait_for(lck, rel_time, [this](){return count < capacity;})){
        return false;
      }

出隊

對于出隊,其實現(xiàn)和入隊基本相同,基本上只需要更改其中的關(guān)鍵判斷和通知。

take函數(shù)的代碼實現(xiàn)為:

void LinkedBlockingQueue::take(int & returnVal) {
  int c;
  {
    std::unique_lock<std::mutex> lck{takeLock};
    if( 0 == count) {
      notEmpty.wait(lck, [this](){return count > 0 ;});
    }
    returnVal = dequeue();
    c = count.fetch_sub(1);
  }

  if( c > 1 ) {
    notEmpty.notify_one();
  }

  if(c == capacity) {
    notFull.notify_one();
  }
}

剩下的實現(xiàn)細節(jié)可以參考我的實現(xiàn)

到此這篇關(guān)于c++實現(xiàn)LinkBlockedQueue的問題的文章就介紹到這了,更多相關(guān)c++實現(xiàn)LinkBlockedQueue內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++深復(fù)制和淺復(fù)制講解

    C++深復(fù)制和淺復(fù)制講解

    這篇文章主要介紹了C++深復(fù)制和淺復(fù)制講解,C++中深復(fù)制和淺復(fù)制最大的區(qū)別在“類包含指針類型的數(shù)據(jù)成員”時,下面感興趣的小伙伴和小編一起進入文章了解更多相關(guān)內(nèi)容吧
    2022-03-03
  • 在C++中實現(xiàn)aligned_malloc的方法

    在C++中實現(xiàn)aligned_malloc的方法

    這篇文章主要介紹了在C++中實現(xiàn)aligned_malloc的方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 基于C語言實現(xiàn)高級通訊錄的示例代碼

    基于C語言實現(xiàn)高級通訊錄的示例代碼

    這篇文章主要為大家詳細介紹了如何利用C語言實現(xiàn)一個高級通訊錄的功能,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的小伙伴可以參考一下
    2023-01-01
  • C語言程序環(huán)境編譯+鏈接理論

    C語言程序環(huán)境編譯+鏈接理論

    這篇文章主要介紹了C語言程序環(huán)境編譯+鏈接理論,下面文章基于C語言的相關(guān)資料展開對編譯和鏈接的詳細介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • 利用C語言實現(xiàn)頁面置換算法的詳細過程

    利用C語言實現(xiàn)頁面置換算法的詳細過程

    一個好的頁面置換算法,應(yīng)具有較低的頁面更換頻率,從理論上講,應(yīng)該保留最近重復(fù)訪問的頁面,將以后都不再訪問或者很長時間內(nèi)不再訪問的頁面調(diào)出,下面這篇文章主要給大家介紹了關(guān)于利用C語言實現(xiàn)頁面置換算法的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • C語言二分查找算法及實現(xiàn)代碼

    C語言二分查找算法及實現(xiàn)代碼

    本文主要介紹C語言的二分查找算法,這里給大家詳細介紹了什么是二分查找,并提供代碼實例,需要的小伙伴可以參考下
    2016-07-07
  • C語言趣味編程之水仙花數(shù)

    C語言趣味編程之水仙花數(shù)

    這篇文章介紹了C語言趣味編程之水仙花數(shù),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-11-11
  • c++11?類中關(guān)于default、explict、implicit、noexcept、final的詳解

    c++11?類中關(guān)于default、explict、implicit、noexcept、final的詳解

    這篇文章主要介紹了c++11?類中關(guān)于default、explict、implicit、noexcept、final的詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • 一文詳解C++17中的結(jié)構(gòu)化綁定

    一文詳解C++17中的結(jié)構(gòu)化綁定

    C++17中的結(jié)構(gòu)化綁定(structured binding)是指將指定名稱綁定到初始化程序的子對象或元素,本文主要來和大家聊聊C++17中結(jié)構(gòu)化綁定的實現(xiàn),感興趣的小伙伴可以了解下
    2023-12-12
  • 基于C語言實現(xiàn)創(chuàng)意多彩貪吃蛇游戲

    基于C語言實現(xiàn)創(chuàng)意多彩貪吃蛇游戲

    這篇文章主要介紹了如何利用C語言實現(xiàn)一個創(chuàng)意多彩貪吃蛇游戲,這是一個純C語言外加easyx庫的繪圖函數(shù)制作而成的有趣小游戲,無需引入額外資源,感興趣的可以動手嘗試一下
    2022-08-08

最新評論