無鎖隊列設計思路以及簡要代碼

文章目錄

  • 非并發的一寫一讀環形隊列
  • 多讀多寫環形隊列

非并發的一寫一讀環形隊列

在這里插入圖片描述

讀指針:
1、先判斷是否有數據
2、讀取數據
3、操作指針
寫指針:
1、先判斷空間是否足夠
2、寫入數據
3、操作指針·
所以代碼也十分簡單:

bool putqueue(void* pData)
{ST_NODE* ptr = NULL;do {ptr = pWrite;if ((uiQueueSize - ((pWrite + uiQueueSize - pRead) % uiQueueSize) - 1 > 0) || (NULL= *ptr)) // 隊列滿了 {return false;}} while(!_sync_bool_compare_and_swap(pWrite, ptr, ptr + 1)) // 競爭到寫指針if (pWrite >= pstBegin) {pWrite = pstBegin;}*ptr = pData;return true;
}

那么在多線程多讀多寫的情況下,該如何設計呢?

多讀多寫環形隊列

核心問題是:
1、多個線程如何競爭操作一個指針?
思路:利用CAS(compare & swap)確保只有一個線程能把指針從當前位置指向下一個位置
2、先操作指針還是先操作數據?

  • 先操作指針,有可能導致數據還沒讀,就被寫入方覆蓋
  • 先讀/寫數據,可能無法競爭到指針導致錯誤
  • 解決方案:標記法,已讀取得數據置為NULL,未讀數據為實際數據得指針,讀寫前先判斷標記。
    在這里插入圖片描述
void* getqueue()
{ST_NODE* ptr = NULL;ST_NODE* current = NULL;do {ptr = pRead;if (((pWrite + uiQueueSize - pRead) % uiQueueSize) > 0 || (NULL= ptr)) // 隊列空{return NULL;}} while(!_sync_bool_compare_and_swap(pRead, ptr, ptr + 1)) // 競爭到讀指針if (pRead >= pstEnd) {pRead = pstEnd;}current = *ptr;*ptr = NULL;return *current;
}

此時也會出現一些極端的問題:
1、CAS指令的ABA問題:兩個線程同時讀/寫同一個位置,第一個線程獲取讀/寫權限后,第二個線程掛起。
指針有可能轉一圈回到原來位置,導致第二個線程恢復運行,從而第二個線程CAS成功。極端情況下會導致讀指針越過寫指針。
解決方案:通過一個唯一id:seq替換指針,seq為64位整數,自增且永不重復。指針 = 隊列首地址 + seq % 隊列長度

class mqueue
{
public:mqueue() {read_seq_ = write_seq_ = 0;memset(queue_arr_, 0, sizeof(queue_arr_));}bool push_back(void* data);     // 插入元素void* pop_front();      // 取出元素
private:void* queue_arr_[MAXN];volatile uint64_t read_seq_;volatile uint64_t write_seq_;
};bool mqueue::push_back(void* data) 
{do {uint64_t cur_seq = write_seq_; // 保留原始值,避免處理過程被其他線程改變if (cur_seq >= read_seq_ + MAXN || queue_arr_[cur_seq % MAXN]){return false;   // 隊列滿了,等讀線程讀取}if (_sync_bool_compare_and_swap(&write_seq_, cur_seq, cur_seq + 1)){queue_arr_[cur_seq % MAXN] = data;return true;}} while (true);
}void* mqueue::pop_front()
{do{uint64_t cur_seq = read_seq_;   // 保留原始值,避免處理過程被其他線程改變if (cur_seq >= write_seq_ || queue_arr_[cur_seq % MAXN] == NULL){return NULL;    // 隊列空,等待寫線程寫入 }if (_sync_bool_compare_and_swap(&read_seq_, cur_seq, cur_seq + 1)){void* data = queue_arr_[cur_seq % MAXN];queue_arr_[cur_seq % MAXN] = NULL;return data;}} while (true);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376673.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376673.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376673.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vs 2012,vs 2013問題系列

系統環境: 64位 win7 1,問題: 之前能連接tfs進行源碼管理,期間有改過本地電腦的時間,再后來使用vs 2012連接tfs卻失敗了。錯誤碼:TF31002。排除了網絡問題,用戶權限問題,tfs服務器問…

Linux查看系統信息的一些命令

轉:http://www.cnblogs.com/chenwenbiao/archive/2011/07/18/2109983.html 系統 # uname -a # 查看內核/操作系統/CPU信息 # head -n 1 /etc/issue # 查看操作系統版本 # cat /proc/cpuinfo # 查看CPU信息 # hostname # 查看計…

CPU Cache對于并發編程的影響

文章目錄引子CPU Cache對于并發的影響讀寫順序對性能的影響字節對齊對Cache的影響小結引子 下面給出兩個極其相似的代碼&#xff0c;運行出的時間卻是有很大差別&#xff1a; 代碼一 #include <stdio.h> #include <pthread.h> #include <stdint.h> #includ…

textarea 在瀏覽器中固定大小和禁止拖動

http://blog.sina.com.cn/s/blog_641d569301011naz.html HTML 標簽 textarea 在大部分瀏覽器中只要指定行&#xff08;rows&#xff09;和列&#xff08;cols&#xff09;屬性&#xff0c;就可以規定 textarea 的尺寸&#xff0c;大小就不會改變&#xff0c;不過更好的辦法是使…

hibernate操作時報錯

報錯&#xff1a;[ERROR] AbstractBatcher Exception executing batch: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1原因&#xff1a;視具體情況而定&#xff0c;我這邊是代碼被修改過…

bugfix:MySQL內存使用率無限增長以及kill手法

問題&#xff1a;昨天mysql 宕機了一次&#xff0c;重啟&#xff0c;然后繼續運行業務代碼的時候發現問題&#xff0c;mysql內存占用率上升較快&#xff0c;于是搜了搜&#xff0c;遇到一個&#xff1a; http://blog.itpub.net/29510932/viewspace-2129312/ 根據思路&#xff0…

軟工之初識

我們之前已經在完全不懂軟件工程的情況下&#xff0c;已經做完了兩個小系統&#xff0c;雖然能夠運行&#xff0c;但其中有很多的問題&#xff0c;學習軟工就是讓我們在工程學原理的指導之下去開發和設計軟件。 軟件工程同大多數書講的都是一樣的&#xff0c;首先對軟件工程有一…

perf +火焰圖使用

以mysqld進程為例&#xff1a; [rootVM-90-225-centos ~]# ps -ef | grep mysqld root 9808 9621 0 19:30 pts/7 00:00:00 grep --colorauto mysqld root 16104 1 0 17:30 pts/0 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir/usr/loc…

Mysql 遇到的編碼問題。

今天幫小朋友做一個項目&#xff0c;碰到一個挺搞的問題。在幫她安裝mysql的時候一直是next&#xff0c;沒有去注意一些細節&#xff0c;不曉得有沒有漏掉設置編碼那一部分。。 結果在用sql文件導入數據庫MySQL -h localhost -u root -p xxx < e:\xxx.sql 執行的時候錯誤提…

在一個字符串中找到第一個只出現一次的字符

題目&#xff1a;在一個字符串中找到第一個只出現一次的字符&#xff0c;如輸入abaccdeff&#xff0c;則輸出b&#xff1b;具體實現如下&#xff1a;#include <iostream> #include <string> using namespace std; void FindChar(const string &strBuf) {int nA…

py腳本:獲取進程信息

這里以mysqld進程為例子 # pip install psutil import psutil import time import re, sys# x:進程name y:非進程name # 由于這里監控的是mysqld&#xff0c;如果不加限制的話會先識別mysqld_safe&#xff0c;所以要加上mysql_safe的判別 def processinfo(x, y):p_list psut…

sysctl -P 報錯解決辦法

sysctl -P 報錯解決辦法問題癥狀修改 linux 內核文件 #vi /etc/sysctl.conf后執行sysctl -P 報錯error: "net.bridge.bridge-nf-call-ip6tables" is an unknown keyerror: "net.bridge.bridge-nf-call-iptables" is an unknown keyerror: "net.bridg…

-bash: belts.awk: command not found

執行awk命令時&#xff0c;沒有問題。可是執行awk腳本時&#xff0c;出現這個問題&#xff1a;-bash: belts.awk: command not found。 既然之前直接執行awk命令沒有問題&#xff0c;說明awk已經裝了&#xff0c;本身是沒有問題的。那就說明路徑不對&#xff0c;執行echo $PATH…

nagios快速安裝

1、安裝軟件包&#xff08;準備軟件包&#xff09; yum install httpd gcc glibc glibc-common gd gd-devel 2、建立一個賬戶 創建一個名為nagios的帳號并給定登錄口令 /usr/sbin/useradd nagios passwd nagios 創建一個用戶組名為nagcmd用于從Web接口執行外部命令。將nagios用…

零拷貝機制在文件傳輸中的使用手法

文章目錄文件傳輸&#xff08;讀取與發送&#xff09;中的拷貝與上下文切換零拷貝技術sendfilesendfile SG-DMAmmap writespliceDirect I/O經典應用文件傳輸&#xff08;讀取與發送&#xff09;中的拷貝與上下文切換 如果服務端要提供文件傳輸的功能&#xff0c;最簡單的方式…

Effective Modern C++翻譯(3)-條款2:明白auto類型推導

條款2 明白auto類型推導 如果你已經讀完了條款1中有關模板類型推導的內容&#xff0c;那么你幾乎已經知道了所有關于auto類型推導的事情&#xff0c;因為除了一個古怪的例外&#xff0c;auto的類型推導規則和模板的類型推導規則是一樣的&#xff0c;但是為什么會這樣呢&#xf…

信息論與編碼復習

若信源有m種消息&#xff0c;且每個消息是以相等可能產生的&#xff0c;則該信源的信息量可表示為Ilogm。 信息率是通過接收到的信息可獲得的發送信息的信息量,即互信息。單位:bit/符號。 信息速率是單位時間內傳輸的信息量。單位:bit/s 碼字CodeWord。由若干個碼元組成&#x…

拖拽碰撞效果最終版

拖拽碰撞效果最終版&#xff0c;沒準還有bug&#xff0c;不過現在在各個瀏覽器下效果是對的&#xff0c;代碼需要精簡一些&#xff0c;以后有時間了在弄吧&#xff0c;現在先不理了&#xff0c;感冒了&#xff0c;沒有心情整理 <!DOCTYPE HTML> <html lang"en-US…

Python 如何利用函數修改函數外list?

#在函數內修改列表的時候&#xff0c;在列表后面加上[:]&#xff0c;無論幾維列表均可。 def foo(listA):listA[:] [1,2,3] def foo2(listB):listB [1,2,3] listA [4,5,6] listB [4,5,6] foo(listA) foo2(listB) print listA #result: [1,2,3] print listB #result: [4,5,6…

圖片壓縮android bitmap compress(圖片壓縮)

本文純屬個人見解&#xff0c;是對前面學習的總結&#xff0c;如有描述不正確的地方還請高手指正~ 有些場景中&#xff0c;須要照相并且上傳到服務&#xff0c;但是由于圖片的巨細太大&#xff0c;那么就 上傳就 會很慢(在有些網絡情況下)&#xff0c;而且很耗流量&#xff0c;…