單生產者單消費者的環形佇列
環形佇列設計如下:
template <class T> class ring { puclic: explicit ring(int size): m_maxsize(size), m_rp(0), m_wp(0) { if (size < 2) { throw std::runtime_error("too few elements, size must grater than 1"); } m_array = new T[size+1]; } ~ring { delete [] m_array; } bool full()const { return inc(wp) == rp; } bool empty()const { return rp == wp; } int inc(int n)const { return ++n % (maxsize+1); } int push_back(const T& v) { if (full()) { return -1; } m_array[m_wp] = v; m_wp = inc(m_wp); return 0; } int pop_front(T& v) { if (empty()) { return -1; } v = m_array[m_rp]; m_rp = inc(m_rp); return 0; } size_t size()const { size_t n = m_wp - m_rp; return n > 0 ? n : m_maxsize + n; } private: T* m_array; int m_maxsize; int m_rp __attribute__((align(8))); int m_wp __attribute__((align(8))); }
考慮如下情況,單生產者,單消費者
1.讀執行緒追趕寫執行緒,但empty()條件rp == wp一直為true,即使不加鎖也執行緒安全
2.寫執行緒追趕讀執行緒,單full()條件wp++ == rp一直
3.極端情況下
rp=wp=m_maxsize
讀寫執行緒按如下指令執行:
寫執行緒 讀執行緒
wp++
empty() rp == wp 為false
rp++
rp = 0 rp翻轉
empty()為false 可讀
wp = 0 wp翻轉
rp++ rp=1,這個時候讀索引已經在寫索引前,資料讀取異常
4.所以rp,wp的操作必須是原子的,根據Intel手冊8.1.1節的介紹:
從Intel486 processor開始,以下的基本記憶體操作是原子的:
• Reading or writing a byte(一個位元組的讀寫)
• Reading or writing a word aligned on a 16-bit boundary(對齊到16位邊界的字的讀寫)
• Reading or writing a doubleword aligned on a 32-bit boundary(對齊到32位邊界的雙字的讀寫)
從Pentium processor開始,除了之前支援的原子操作外又新增了以下原子操作:
• Reading or writing a quadword aligned on a 64-bit boundary(對齊到64位邊界的四字的讀寫)
• 16-bit accesses to uncached memory locations that fit within a 32-bit data bus(未快取且在32位資料匯流排範圍之內的記憶體地址的訪問)
所以__attribute__((align(8)))可保證索引讀寫的原子性
相關推薦
單生產者單消費者的環形佇列
環形佇列設計如下: template <class T> class ring { puclic: explicit ring(int size): m_maxsize(size), m_rp(0), m_wp(0) { i
併發無鎖佇列學習(單生產者單消費者模型)
1、引言 本文介紹單生產者單消費者模型的佇列。根據寫入佇列的內容是定長還是變長,分為單生產者單消費者定長佇列和單生產者單消費者變長佇列兩種。單生產者單消費者模型的佇列操作過程是不需要進行加鎖的。生產者通過寫索引控制入隊操作,消費者通過讀索引控制出佇列操作。二者
併發無鎖佇列學習之二【單生產者單消費者】
1、前言 最近工作比較忙,加班較多,每天晚上回到家10點多了。我不知道自己還能堅持多久,既然選擇了就要做到最好。寫部落格的少了。總覺得少了點什麼,需要繼續學習。今天繼續上個開篇寫,介紹單生產者單消費者模型的佇列。根據寫入佇列的內容是定長還是變長,分為單生產者單消費者定長佇列和單生產者單消費者變長佇列兩
19.執行緒同步:訊號量—>[單生產者/單消費者]單鏈表的插入和刪除
1.訊號量 1.訊號量本質 訊號量是鎖,是一種升級的mutex 訊號量在初始化時,可以指定共享資源的數量 2.相關函式 #include<semaphore.h> //標頭檔案 sem_t sem; //訊號量型別 int sem_destroy(se
基於單鏈表和基於環形佇列的生產者單消費者模型
先來介紹一下生產者消費者模型,舉一個常見的例子: 生活中,我們會經常去超市買東西,這裡涉及到了三個事物:我們、超市、供貨商。很容易就可以想到,我們就相當於消費者,而供貨商就相當於生產者,那麼超市就算是一個交易場所了。 對於生產者消費者模型我們可以簡單的總結一
單生產者,單消費者無鎖佇列實現(c)
根據上面連結所說的原理實現的單生產者,單消費者無鎖佇列 bool __sync_bool_compare_and_swap (type *ptr, type oldval,type newval, ...) 函式提供原子的比較和交換,如果*ptr == oldval
一個取消多生產者單消費者的日誌執行緒池服務
package concurrent._ThreadPool.logService; import net.jcip.annotations.GuardedBy; import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; import java.io.
基於環形佇列的生產者消費者模型
之前的Blog基於Queue的生產者消費者模型,已經談過了基於queue的生產消費模型,其空間是可以動態分配的。而現在是基於固定大小的環形佇列重寫這個程式。 基於環形佇列的生產消費模型 環形佇列採用陣列模擬,用模運算來模擬環狀特性 環形結構起始狀態和結束狀態都是一樣
生產者與消費者模型(基於單鏈表、環形佇列、多執行緒、多消費多生產)
#include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <semaphore.h> #define SIZE 10 sem_t
基於單鏈表、環形佇列(併發有鎖)的多執行緒生產者消費者模型
基於單鏈表 基於環形佇列 1、環形緩衝區 緩衝區的好處,就是空間換時間和協調快慢執行緒。緩衝區可以用很多設計法,這裡說一下環形緩衝區的幾種設計方案,可以看成是幾種環形緩衝區的模式。設計環形緩衝區涉及到幾個點,一是超出緩衝區大小的的索引如何處理,
java簡單實現非同步佇列:使用生產者與消費者模型
package com.yunshouhu; import java.util.concurrent.*; //java簡單實現非同步佇列:使用生產者與消費者模型 public class MyAsynQueue { // http://www.importnew.com/22519.h
activeMQ的建立生產者和消費者的demo(佇列模式)
佇列模式流程圖(有點醜,網上查的) 程式碼實現生產者 String url="tcp://47.93.188.85:61616"; //目標名稱 String name="test"; //建立連線工廠 ConnectionFactory connectionFac
佇列實現生產者與消費者
import threading,time,queue,randomdef scz(): while True: num=random.randint(1,100000) q.put(num)#放進佇列 print("生產者產生了%d資料" %(num)) time.sleep(5) q.task_do
1.【RabbitMQ】生產者,消費者,通道,佇列,交換器和繫結
瞭解訊息通訊中的一些重點概念對於深化對RabbitMQ的理解有重要的意義;下面從生產者,消費者,通道,佇列,交換器和繫結,來介紹他們在訊息通訊過程中的角色和作用; 生產者: 建立訊息,然後釋出到代理伺服器(RabbitMQ) 消費者: 連線到代理伺服器
RabbitMQ訊息佇列生產者和消費者
概述 生產者生產資料至 RabbitMQ 佇列,消費者消費 RabbitMQ 佇列裡的資料。 詳細 一、準備工作 1、安裝 RabbitMQ 服務和 RabbitMQ Management。 2、在 RabbitMQ 管理介面建立使用者 test
守護程序,互斥鎖,IPC,佇列,生產者與消費者模型
小知識點:在子程序中不能使用input輸入! 一.守護程序 守護程序表示一個程序b 守護另一個程序a 當被守護的程序結束後,那麼守護程序b也跟著結束了 應用場景:之所以開子程序,是為了幫助主程序完成某個任務,然而,如果主程序認為自己的事情一旦做完了就沒有必要使用子程序了,就可以將子程序設定為守護程序
【演算法導論】10.1-5單陣列實現雙端佇列
演算法導論第三版P131 題目: 10.1-5 棧插入和刪除元素只能在同一端進行,佇列的插入操作和刪除操作分別在兩端進行,與它們不同的,有一種雙端佇列(deque),其插入和刪除操作都可以在兩端進行。寫出4個時間均為O(1)的過程,分別實現在雙端佇列插入和刪除元素的操作,該
Java阻塞佇列實現生產者和消費者
生產者 import java.util.Random; import java.util.concurrent.BlockingQueue; //生產者 public class Producer implements Runnable{ private final Block
【RabbitMQ】生產者,消費者,通道,佇列,交換器和繫結
瞭解訊息通訊中的一些重點概念對於深化對RabbitMQ的理解有重要的意義;下面從生產者,消費者,通道,佇列,交換器和繫結,來介紹他們在訊息通訊過程中的角色和作用; 生產者: 建立訊息,然後釋
python 程序鎖 生產者消費者模型 佇列 (守護程序,資料共享等)
#######################總結####### 主要理解 鎖 生產者消費者模型 解耦用的 共享資源的時候 是不安全的 所以用到後面的鎖 守護程序:p.daemon = True #將該程序設定為守護