一種讀寫可併發進行的佇列的實現方法

2021-08-31 08:09:23 字數 1207 閱讀 9886

一.

1 背景

目前採用多執行緒的處理機制中,如下處理方式是比較常見的:

乙個執行緒負責將上游資料放到乙個公共佇列中,另外乙個執行緒從公共佇列中取出資料進行處理。讀取操作都需要共用乙個互斥量來保證執行緒安全,這樣寫資料和取資料的操作實際上是序列的,有些時候,這個操作將對軟體處理效能造成一定影響。如果我們能夠實現乙個佇列,讀取操作不需要任何互斥量保護就可以保證執行緒安全,那麼讀寫執行緒的處理能力將得到明顯提高。

實際上就是保證佇列的讀取介面和寫入介面之間不存在併發衝突,即乙個執行緒只呼叫讀取介面,乙個執行緒只呼叫寫入介面,這兩個執行緒是不需要進行任何同步動作的;如果多個執行緒同時呼叫讀取介面或者同時呼叫寫入介面,那麼讀取介面和寫入介面可以用不同的互斥量進行同步;最終達到我們的目的:多個執行緒中,讀取速率不會影響寫入的速率,反之亦然。

除了讀取操作外,很多地方可能還要知道佇列的大小,比如內部除錯資訊,或者實現中需要限制佇列的最大容量等,這在讀寫兩個執行緒都可能用到的,也希望在任意處理執行緒中不用加鎖就可以取到這個資訊,這個介面和讀寫介面都不存在併發衝突的問題,從而提高執行效率。

軟體開發網

2 實現方案

需要進行執行緒同步的操作都是因為大家需要修改(有的執行緒修改,也有的執行緒訪問)公共資源造成的,只要我們能夠保證忘列表中增加乙個節點和刪除乙個節點都不需要都修改同乙個資源,而且保證待訪問的資源始終有效,那麼就可以做到讀取操作本身就是執行緒安全的。

下面是乙個列表的簡單實現。

struct listnode

struct list

void push_back(int data)

}void pop_front()

int front()

}上面的實現,因為增刪操作都可能修改內部的beg,end變數,無法做到執行緒安全的。

如果push_back只修改end變數,pop_front只修改beg變數,那麼這兩個操作就可以做到執行緒安全的。如果列表為空的時候beg,end 都以空指標來表示,就不可能做到這一點。如果列表為空的時候,beg,end也指向乙個固定節點,那麼就可能實現這個操作。如下所示:

struct list…}

當插入資料的時候都是用已有的end節點來儲存資料,然後在生成乙個新的表示結束的節點,如下

void push_back(int data)

這樣在插入資料的時候不需要修改beg變數了。在提取資料的時候也是做類似處理:

void pop_front()

}考慮實際得取值操作

一種可併發讀寫的佇列實現

寫演算法時頭腦要清晰,在頭腦中高速抽象分析,一般都會用迴圈或遞迴思想來完成。1 定義規則 2 確定邊界條件 3 每一步的具體操作和細節注意 例如 c實現迴圈佇列 分析如下 肯定有迴圈操作,要考慮佇列空或者滿,還有越邊界等情況,要迅速準確完成程式必須定義規則,無規矩無以成方圓。1 head和tail兩...

佇列的一種實現 迴圈佇列

佇列的一種實現,迴圈佇列,通過使用固定長度陣列及首尾指標實現佇列的入隊 出隊等 class circularqueue 元素入隊,成功則返回true,否則false param value return public boolean put t value if isempty true tail ...

一種可展開伸縮的tableView實現

簡單實現了乙個可展開收縮的tableview,可多級展開,一次收縮,類似於樹形結構,可擴充套件性強。1 結點型別 inte ce ymtreenode nsobject property nonatomic,copy nsstring nodename 結點名字 property nonatomic...