程序同步 生產者消費者模型 以及解決方法

2022-02-18 09:09:03 字數 1785 閱讀 7821

生產者和消費者問題是執行緒模型中的經典問題:生產者和消費者在同一時間段內共用同乙個儲存空間,生產者往儲存空間中新增產品,消費者從儲存空間中取走產品,當儲存空間為空時,消費者阻塞,當儲存空間滿時,生產者阻塞。

為什麼要使用生產者和消費者模式:

生產者——消費者模型中,生產者和消費者執行緒之間需要傳遞一定量的資料,兩個執行緒會使用乙個特定大小的共享環形緩衝器。

生產者向緩衝器中寫入資料,直到它到達緩衝器的終點;然後它會再次從起點重新開始,覆蓋已經存在的資料。消費者執行緒則會讀取生成的資料。

在生產者——消費者例項中,對於同步的需求有兩個部分:

1.如果生產者執行緒生成資料的速度太快,那麼將會把消費者執行緒還沒有讀取的資料覆蓋;

2.如果消費者執行緒讀取資料的速度過快,那麼它就會越過生產者執行緒而讀取一些垃圾資料。

讓生產者執行緒填滿緩衝器,然後等待消費者執行緒讀取完緩衝器中全部資料。

使用兩個訊號量:freespace 與 usedspace

freespace 訊號量控制生產者執行緒寫入資料的那部分緩衝器, usedspace 訊號量則控制消費者執行緒讀取資料的那部分緩衝器區域。

這兩個區域是相互補充的。

常用緩衝區容量值初始化 freespace 訊號量,意味著它最多可以獲取的緩衝器資源量。

在啟動這個應用程式時,消費者執行緒就會獲得自由的位元組並把它們轉換為用過的位元組。

用0初始化usedspace訊號量,以確保消費者執行緒不會在一開始就讀取到垃圾資料。

在生產者執行緒中,每次反覆寫入都是從獲取乙個 freespace 開始。

如果該緩衝器中充滿了消費者執行緒還沒有讀取的資料,那麼對acquire()的呼叫就會被阻塞,直到消費者執行緒開始消費這些資料。

一旦生產者執行緒獲取這一位元組,就寫入資料,並將這個位元組釋放為 usedspace ,以讓消費者執行緒讀取到。

在消費者執行緒中,我們從獲取乙個 usedspace 開始。

如果緩衝器中還沒有任何可用的資料,那麼將會阻塞對acquire()呼叫,直到生產者執行緒生產資料。

一旦獲取到這個位元組,就使用資料,並把位元組釋放為 freespace ,這樣,生產者執行緒就可以再次寫入。

上述方法在只有乙個生產者和乙個消費者時能解決問題。對於多個生產者或者多個消費者共享緩衝區的情況,該演算法也會導致競爭條件,出現兩個或以上的程序同時讀或寫同乙個緩衝區槽的情況。

為了保證同一時刻只有乙個生產者能夠執行 putitemintobuffer()。也就是說,需要尋找一種方法來互斥地執行臨界區的**。為了達到這個目的,可引入乙個二值訊號燈 mutex,其值只能為 1 或者 0。如果把執行緒放入 down(mutex) 和 up(mutex) 之間,就可以限制只有乙個執行緒能被執行。

static unsigned char g_buff[size] = ;

static qsemaphore g_sem_free(size);

static qsemaphore g_sem_used(0);

static qsemaphore mutex(1);

class producer : public qthread

std::cerr<<"p";

++usedspace;

bufferisnotempty.wakeall();

mutex.unlock();}}

};class consumer : public qthread

std::cerr<<"c";

--usedspace;

bufferisnotfull.wakeall();

mutex.unlock();

}std::cerr<

OS 程序同步 生產者消費者

注意 在每個程式中多個wait操作順序不可以顛倒。應先執行對資源訊號量的wait操作,然後再執行對互斥訊號量的wait操作,否則可能引起程序死鎖。概述 p操作 同步再前,互斥再後 記錄型訊號量 include using namespace std int in 0 佇列的隊首 int out 0 ...

C 模擬「生產者消費者」程序同步問題

include include include include include using namespace std const int limit 30 生產總量 const int maxsize 10 緩衝區大小 const int kind 7 int bufidx 0 當前緩衝區下標 s...

Linux下程序同步問題 生產者消費者

設計思路,首先有緩衝區內資源,生產者消費者都用,而且是資源訊號量,那麼需要建立兩個訊號量,乙個代表空閒的個數,乙個代表非空閒個數。同時緩衝區的使用是互斥的,所以需要建立乙個互斥訊號量。include include include include include include include in...