生产者和消费者代码———操作系统_操作系统基础15-生产者消费者问题
在上一篇操作系統基礎14提到通過信號量解決生產者消費者問題。本篇來詳細說說操作系統中的經典問題-生成者消費者問題
生產者消費者問題 (Producer-consumer problem)
該問題是一個著名的同步問題。通俗的描述是:一群生產者進程正在生產產品,并將這些產品提供給消費者進程去消費。為使生產者和消費者能夠并發執行。在兩者之間設置了一個公共區域,生產者進入公共區域生產產品并放入其中。消費者進入公共區域并取走產品進行消費。
當一個生產者進入公共區域生產產品時,其他生產者和消費者不能同時進入公共區域生產產品或消費產品。當一個消費者進入公共區域消費產品的時候,其它消費者和生產者不能同時進入該區域消費產品或生產產品。也就是說,任意時刻,最多只允許一個生產者或一個消費者進入公共區域。即生產者和消費者必須互斥的訪問公共區域。
當產品放滿公共區域時,生產者必須等待,使消費者先消費。當公共區域為空時,消費者必須等待,使生產者先生產。即在公共區域為空或為滿時,生產者或消費者在執行時要滿足一定的先后順序。即生產者與消費者對公共區域的訪問必須同步。
根據以上描述,可以得出如下結論:
(1)生產者與生產者之間存在競爭即互斥關系
(2)消費者與消費者之間存在競爭即互斥關系
(3)生產者與消費者之間存在互斥與同步關系
以上三個結論可以概括為:三種關系,兩種角色,一個臨界區。即“三二一”規則
生產者消費者問題也稱有限緩沖問題(Bounded-buffer problem),從多線程同步來看,該問題描述了共享固定大小緩沖區的兩個線程——即所謂的“生產者”和“消費者”——在實際運行時會發生的問題。生產者的主要作用是生成一定量的數據放到緩沖區中,然后重復此過程。與此同時,消費者也在緩沖區消耗這些數據。該問題的關鍵就是要保證生產者不會在緩沖區滿時加入數據,消費者也不會在緩沖區中空時消耗數據。
.
要解決該問題,就必須讓生產者在緩沖區滿時休眠(要么干脆就放棄數據),等到下次消費者消耗緩沖區中的數據的時候,生產者才能被喚醒,開始往緩沖區添加數據。同樣,也可以讓消費者在緩沖區空時進入休眠,等到生產者往緩沖區添加數據之后,再喚醒消費者。通常采用進程間通信的方法解決該問題。緩沖區是臨界資源,必須互斥的訪問,所以如果解決方法不夠完善,則容易出現死鎖的情況。出現死鎖時,兩個線程都會陷入休眠,等待對方喚醒自己。該問題也能被推廣到多個生產者和消費者的情形。
有限緩沖問題
問題分析
該問題需要注意的幾點:
- 在緩沖區為空時,消費者不能再進行消費
- 在緩沖區為滿時,生產者不能再進行生產
- 在一個線程進行生產或消費時,其余線程不能再進行生產或消費等操作,即保持線程間的同步
- 注意條件變量與互斥鎖的順序
資源可以使用
由于前兩點原因,因此需要保持線程間的同步,即一個線程消費(或生產)完,其他線程才能進行競爭CPU,獲得消費(或生產)的機會。對于這一點,可以使用條件變量進行線程間的同步:生產者線程在product之前,需要wait直至獲取自己所需的信號量之后,才會進行product的操作;同樣,對于消費者線程,在consume之前需要wait直到沒有線程在訪問共享資源(緩沖區),再進行consume的操作,之后再解鎖并喚醒其他可用阻塞線程。
等待使用資源
通用實現
也就是上一篇中的通過信號量機制(P、V操作)解決
生產者和消費者進程共享以下數據結構:
int n;? ? ? ? ? //緩沖池有n個緩沖區,每個緩沖區可存一個數據項semaphore? mutex = 1;? ? //信號量 mutex 提供緩沖池訪問的互斥要求,并初始化為1semaphone? empty = n; //信號量 empty 表示空的緩沖區數量semaphone? full = 0? ? ? //信號量 full 表示滿的緩沖區數量生產者(producer)和消費者(consumer)進程結構:
producer(){ while(1){ 生成一個產品; P(empty); //消耗一個空閑緩沖區 P(mutex); 把產品放入緩沖區; V(mutex); V(full) //增加一個產品 }}consumer(){ while(1){ P(full); //消耗一個產品 P(mutex); 從緩沖區取出一個產品; V(mutex); V(empty); //增加一個空閑緩沖區 使用產品; }}生產者消費者進程結構
互斥的實現是在同一個進程中進行的一對PV操作。
同步的實現是在兩個進程中進行的,在一個進程中執行P操作,在另一個進程中執行V操作。
能否改變P、V操作的順序
若此時緩沖區內已經放滿產品,則 empty = 0,full = 0
則生產者進程執行① 使mutex變為0,再執行②,由于已沒有空閑緩沖區,因此生產者被阻塞。由于生產者被阻塞,因此切換回消費者進程。消費者進程執行③,由于mutex為0,即生產者還沒釋放對臨界資源的“鎖”,因此消費者也被阻塞。這就造成了生產者等待消費者釋放空閑緩沖區,而消費者又等待生產者釋放臨界區的情況,生產者和消費者循環等待被對方喚醒,出現“死鎖”。
同樣的,如何緩沖區中沒有產品,即 empty = n,full = 0
按③④①的順序執行也會發生死鎖。
因此,實現互斥的P操作一定要在實現同步的P操作之后。V操作不會導致進程阻塞,因此兩個V操作順序可以交換。
小結
生成者和消費者問題是一個互斥、同步的綜合問題。隱含著兩對同步關系。有時候是消費者需要等待生產者生成,有時候是生成者等待消費者消費,這是兩個不同的“一前一后問題”,因此也需要設置兩個同步信號量。
總結
以上是生活随笔為你收集整理的生产者和消费者代码———操作系统_操作系统基础15-生产者消费者问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 找不到金税盘是什么原因
- 下一篇: java信息管理系统总结_java实现科