Linux 基於訊號量的生產者消費者模型

2021-09-29 03:48:06 字數 2961 閱讀 9972

不是用一般佇列作為緩衝區,而是用環形佇列作為緩衝區

不使用pthread_mutex,而使用訊號量來實現生產者消費者的同步。

使用的是posix訊號量而不是之前的system_v,因為這兩個訊號量作用相同,都用於同步操作,但posix可以用於執行緒間同步。

這裡可以暫時把訊號量當成乙個計數器,當值未1時代表,有乙份資源可以使用,有人申請這份資源時,值會減1,當值為0時,,其他人想繼續申請這份資源,會被掛起放入等待佇列中。

初始化訊號量,在引數中可以傳入非0的值n,代表有n個資源。

訊號量有兩個重要的操作,pv操作,p操作,釋放資源,會使資源數+1,v操作,申請資源,會使資源數減1,下面是posix的具體函式。

初始化訊號量

#include

intsem_init

(sem_t *sem,

int pshared,

unsigned

int value)

;引數:

pshared:0表示執行緒間共享,非0表示程序間共享

value:訊號量初始值

銷毀訊號量

int

sem_destroy

(sem_t *sem)

;

等待訊號量

int

sem_wait

(sem_t *sem)

;功能:等待訊號量,將訊號量的值減1

發布訊號量

int

sem_post

(sem_t *sem)

;功能:發布訊號量,表示資源使用完畢,可以歸還資源了,將訊號量+

1

和普通佇列不同,迴圈佇列首尾相接,生產者p向佇列中不斷插入資料,當插入滿了後,消費者c從佇列中讀取資料,當消費者c處理完資料後佇列成空,生產者p又在佇列中插入資料。

但是有乙個問題出現了,當p和v同時指向乙個位置時,你無法判斷是佇列是空還是滿(這裡暫時不考慮,p比c多走了n圈的可能)

上面的訊號量解決了這個問題,訊號量相當於計數器,所以可以設定兩個訊號量,乙個記錄佇列裡插入資料的數量,另乙個訊號量記錄佇列裡未插入的空間的數量。

實際上我們可以用乙個訊號量,判斷當兩個指標指向同一片位址時是滿還是空,為什麼需要兩個訊號?

原因,假如只有乙個訊號量,則只能對乙個物件進行限制,假設訊號量記錄未插入的空間記錄為0時,消費者阻塞,生產者生產,但是buffer時有限的,但是沒有訊號量記錄插入的數已經使佇列滿了,換句話說生產者的生產行為是不受限制的,不滿足生產者消費者模型。

解決完了判斷佇列滿或空後,還有第二個問題,在stl中沒有環形佇列,需要我們自己實現,這個難不倒我們,可以利用雜湊表的開雜湊思想,用陣列作為環形佇列,對插入的位址進行取模,作為陣列下標。

超過陣列的長度,進行取模操作

還剩下最後乙個問題,如何確保,生產者和消費在重合後最多差距為1圈。

因為開始的時候記錄的空格子訊號量計算為最大,記錄插入資料的訊號量為0。

因此,對於消費者申請資源會被掛起,這樣生產者一定會先進行生產,假設生產者的生產速度大於消費者的處理資料的速度,當生產者把迴圈佇列插滿後,錄的空格子訊號量計算為0,當生產者進行下次生產,申請空的資源也會被掛起,直到,記錄的空格子訊號量不為0為止,這樣就保證了生產者和消費在重合後最多差距為1圈。

下面是根據這種思想,寫出的單生產者消費者模型。

#include

#include

#include

#include

#include

#include

using namespace std;

#define num 8

class ringqueue

~ringqueue()

void

putdata

(const

int& data)

void

getdata

(int

& data)};

void

*producter

(void

* arg)

}void

*consumer

(void

*arg)

}int

main()

上面我們使用了環形緩衝區來代替普通緩衝區,環形緩衝區佇列相對於普通緩衝區有哪些優點?

環形緩衝區所有的push和pop操作都是在乙個固定的儲存空間內進行。而佇列緩衝區在push的時候,可能會分配儲存空間用於儲存新元素;在pop時,可能會釋放廢棄元素的儲存空間。所以環形方式相比佇列方式,少掉了對於緩衝區元素所用儲存空間的分配、釋放。這是環形緩衝區的乙個主要優勢。

思想和基於阻塞佇列的生產者消費者模型沒有大的區別,讀者應該理解生產者消費者模型的意義和解決問題的方法。

Linux訊號量機制(生產者消費者)

該程式為linux訊號量機制實現程式,主要模擬了一般的生產者 消費者問題。生產者 消費者問題是乙個經典的程序同步問題,該問題最早由dijkstra提出,用以演示他提出的訊號量機制。在同乙個程序位址空間內執行的兩個執行緒。生產者執行緒生產物品,然後將物品放置在乙個空緩衝區中供消費者執行緒消費。消費者執...

Linux訊號量機制(生產者消費者)

該程式為linux訊號量機制實現程式,主要模擬了一般的生產者 消費者問題。生產者 消費者問題是乙個經典的程序同步問題,該問題最早由dijkstra提出,用以演示他提出的訊號量機制。在同乙個程序位址空間內執行的兩個執行緒。生產者執行緒生產物品,然後將物品放置在乙個空緩衝區中供消費者執行緒消費。消費者執...

基於訊號量的生產者與消費者模型

本質 計數器 等待佇列 向外提供的使執行流阻塞 喚醒的功能介面 實現同步的原理 程序獲取臨界資源之前,要先獲取訊號量資源 實現互斥的原理 乙個程序獲取了該臨界資源之後,另乙個程序無法再訪問該臨界資源。0 1計數器 對資源進行計數,統計當前的資源數量,通過自身的計數,就可以進行條件判斷,是否能夠進行操...