基於環形佇列的訊息佇列的實現 轉貼CSDN

2021-04-30 04:44:00 字數 1230 閱讀 6630

環形佇列有乙個head指標,有乙個tail指標,假設我們用乙個環形佇列來表示一組資源,

有乙個執行緒產生資源並往佇列裡傳送,另外乙個執行緒從佇列裡取資源,一般的情況下實現

這樣乙個功能需要用到os的互斥/事件/訊號量api,在兩個執行緒執行都很快時這些os的api會帶來

比較大的系統開銷,怎麼樣盡可能的減少os的api呼叫呢,下面是乙個簡單的實現方法(假設只有兩個

執行緒,乙個往佇列裡寫資料,乙個從佇列裡讀資料)

head 與 tail 指標的修改不需要保護,應為分別只有乙個執行緒會修改他們,

put執行緒會讀取tail,修改head, get執行緒會讀取head, 修改tail。

**中最關鍵的是goto語句,防止出現誤等的情況,比如剛開始時,隊列為空,

put執行緒先執行,該執行緒會呼叫increase_semophore語句,然後get執行緒開始執行,

get執行緒第一次會取走乙個element, 然後get執行緒繼續執行,當它試圖取第二個element時,

發現隊列為空,於是等待,這時wait_semophore是會成功的,因為put執行緒之前呼叫了

increase_semophore,雖然這時get執行緒會錯誤的等到資源訊號量,但它會跳到try_get標籤

處重新檢查佇列是否為空,這樣就避免了出現錯誤的結果。同時經過仔細分析,兩個執行緒不會死鎖。

可能大家會擔心乙個問題,head和tail指標沒有被互斥保護起來,雖不會出現程式的錯誤執行,比如head和tail

指標的調整出現問題。因為head和tail都只被乙個執行緒修改,所以不存在多個執行緒修改乙個共享變數的情況,所以

這裡可以對head和tail不加保護,但我們要保證程式不出邏輯錯誤,

比如如果getter正在從乙個滿佇列中取乙個資源時,修改tail指標時,而在之前執行的putter

執行緒已經被阻塞在wait_semophore(sem);語句上,那麼當getter把資源取走後能不能正確的喚醒

putter執行緒呢,答案是肯定可以的,因為getter在從乙個滿佇列中取資源時,need_wake_putter

肯定是會被置為true的,所以increase_semophore(sem)肯定會在取資源後被呼叫,putter執行緒也

會被正確的喚醒。

這個佇列實現機制的優點是最大的避免了呼叫os的互斥/事件/訊號量api,僅在必須的時候呼叫

wait_semophore/increase_semophore api,提高了執行效率。

佇列和環形佇列的實現

1 基本介紹 2 陣列模擬佇列 public class arrayqueuedemo catch exception e break case h trycatch exception e break case e scanner.close flag false break default br...

php基於Redis訊息佇列實現的訊息推送的方法

基本知識點 重點用到了以下命令實現我們的訊息推送 邏輯分析 實現 普通任務指令碼 phpforeach user list as item redispushqueue 守護程序執行 nohup php yourpath redispushqueue.php 開啟守護程序執行,修改檔案之後需要從新啟...

環形佇列的實現原理

環形佇列是乙個首尾相連的fifo 命名管道 的資料結構,它採用陣列的線性空間。它能很快知道佇列是否為滿或者為空,也能很快的訪問資料。原理 記憶體上沒有環形結構,因此環形佇列利用陣列的線性空間來實現。當資料到了尾部時,它將轉回到0位置來處理。這個轉回操作通過取模來執行。構造 邏輯上,將陣列q 0 與q...