前面我們介紹了半同步半非同步執行緒池的概念,下面我們首先說一下同步佇列。
同步佇列是半同步半非同步執行緒池三層中的中間層——排隊層。它一方面提供介面給上面同步服務層新增新任務,一方面提供介面給下面的非同步服務層獲取任務。上層可能是併發的新增任務,因此同步佇列需要保證任務是執行緒安全的,同時它還需要確保任務佇列的長度不會超過上限,避免記憶體消耗過大。
下面我們需要詳細分析同步佇列的功能,它需要的成員和介面,這樣**就可以自然而然的設計出來。
首先我們考慮它需要的成員變數。
佇列
需要有乙個佇列來儲存任務
同步
需要有乙個鎖,來確保從佇列中push和pop執行緒安全,不光如此,和佇列相關的其他操作也需要鎖來保證安全。
條件變數
為什麼需要條件變數?考慮乙個問題,當下面的非同步服務層從同步佇列獲取任務時,同步佇列中沒有任務,對應的執行緒將會等待。那什麼時候喚醒呢?就是當同步服務層新增新的任務的時候,此時佇列非空,那麼就可以喚醒之前的執行緒,取出任務去執行。因此需要乙個條件變數在佇列非空的時候發出通知。
同時,我們上面提到,同步佇列需要確保佇列長度不會過長,因此當佇列已經達到上限時,需要限制同步層新增任務,讓它等待,此時,當非同步服務層取走任務佇列未滿的時候,就要將它喚醒,因此也要乙個條件變數在佇列未滿的時候發出通知。
介面考慮它需要的介面。
新增任務
需要提供介面給同步服務層新增任務進佇列。在新增任務的時候,需要上鎖,確保過程是執行緒安全的。同時需要判斷現在佇列中任務數量是否到達上限,如果達到上限,需要等待佇列未滿條件變數發出通知。
取出任務
需要提供介面給非同步服務層取出任務。同樣,在取任務的時候,需要上鎖,確保過程是執行緒安全的。同時需要判斷現在佇列是否為空,如果為空,則需要等待佇列非空條件變數發出通知。
上面是一些最主要的成員,另外還需要考慮限制佇列長度的變數,以及一些其他的介面,例如查詢佇列狀態(滿或者空),佇列中任務數,以及清空佇列等。
#ifndef include_syncqueue__
#define include_syncqueue__
#include
#include
#include
namespace mythreadpool
void
push
(t&& task)
; not_full_variable_.
wait
(lock,
[this])
; queue_.
push
(std::forward
(task));
not_empty_variable_.
notify_one()
;}void
push
(const t& task)
; not_full_variable_.
wait
(lock,
[this])
; queue_.
push
(std::
move
(task));
not_empty_variable_.
notify_one()
;}void
pop(t& task)
; not_empty_variable_.
wait
(lock,
[this])
; task = queue_.
front()
; queue_.
pop();
not_full_variable_.
notify_one()
;}void
pop(std::queue
& tasks)
; not_empty_variable_.
wait
(lock,
[this])
; tasks = std::
move
(queue_)
; not_full_variable_.
notify_one()
;}bool
empty()
;return queue_.
empty()
;}bool
full()
;return max_size_ == queue_.
size()
;}intcount()
;return queue_.
size()
;}void
clear()
; std::queue tmp;
queue_.
swap
(tmp);}
private
: std::mutex mutex_;
std::condition_variable not_full_variable_;
std::condition_variable not_empty_variable_;
std::queue queue_;
int max_size_;};
}#endif
// include_syncqueue__
乍一看**,其實會發現比之前分析功能時設計的豐富一些。下面將詳細說說上面的**,為什麼這樣實現,以及相關的語法。 c 執行緒池實現(三)同步佇列實現
前面設計同步佇列的 下面詳細說說實現。pushvoid push t task not full variable wait lock,this queue push std forward task not empty variable notify one void push const t t...
執行緒程式設計 同步佇列
我們經常會採用生產者 消費者關係的兩個執行緒來處理乙個共享緩衝區的資料。例如一 個生產者執行緒接受使用者資料放入乙個共享緩衝區裡,等待乙個消費者執行緒對資料取出處理。但是如果緩衝區的太小而生產者和消費者兩個非同步執行緒的速度不同時,容 易出現乙個執行緒等待另乙個情況。為了盡可能的縮短共享資源並以相同...
多執行緒和同步佇列
最近要割接個專案,要把另外乙個公司的資料庫裡的一張表倒到我們庫里,資料有一億三千多萬吧。正號也符合生產者和消費者的狀況。以前用過點執行緒池和同步佇列,寫個例子,讓大家拍磚。不多說了,直接上 1.執行緒池 public class threadpool override public void run...