該問題中出現的主要的兩種關係:算法
①生產者—消費者之間的同步關係表現爲:一旦緩衝池中全部緩衝區均裝滿產品時,生產者必須等待消費者提供空緩衝區;一旦緩衝池中全部緩衝區全爲空時,消費者必須等待生產者提供滿緩衝區。
②生產者—消費者之間還有互斥關係:因爲緩衝池是臨界資源,因此任何進程在對緩衝區進行存取操做時都必須和其餘進程互斥進行。緩存
PV操做題目分析的步驟:併發
1.關係分析。找出題目中描述的各個進程,分析它們之間的同步、互斥關係。code
2.整理思路。根據各進程的操做流程肯定PV操做的大體順序。blog
3.設置信號量。設置須要的信號量,並根據題目條件肯定信號量的初值。(互斥信號量初值通常爲1,同步信號量的初值須要看對應資源的初始值是多少)進程
在這裏:資源
互斥的實現是在同一個進程中進行的一對PV操做。同步
同步的實現是在兩個進程中進行的,在一個進程中執行P操做,在另外一個進程中執行V操做。產品
semaphore mutex = 1; //互斥信號量 semaphore empty = n; //同步信號量。空閒緩衝區的數量 semaphore full = 0; //同步信號量。產品的數量,非空緩衝區的數量 producer(){ while(1){ 生成一個產品; P(empty); //消耗一個空閒緩衝區 P(mutex); 把產品放入緩衝區; V(mutex); V(full) //增長一個產品 } } consumer(){ while(1){ P(full); //消耗一個產品 P(mutex); 從緩衝區取出一個產品; V(mutex); V(empty); //增長一個空閒緩衝區 使用產品; } }
實現互斥的P操做必定要放在實現同步的P操做以後!it
咱們觀察上面的代碼,生產者生產產品和消費者使用產品這兩個操做都是放在各自進程的PV操做以外的,那麼能不能放在各自的PV操做以內呢?其實從邏輯上來講是能夠的,好比從緩衝區取出一個產品以後當即使用這個產品,可是這樣就會形成臨界區的代碼量變大,消費者進程訪問臨界區將會耗費更多的時間,若此時有別的進程想要訪問臨界區是會被阻塞的,若將這些不是很非代碼也放入臨界區,會形成進程的併發度下降。
試分析下列算法在解決生產者/消費者同步問題時會產生什麼後果,並進行改正。設信號量mutex用於生產者與消費者的互斥,初值爲1;設avail是生產者的私有信號量,表示緩衝區的空單元數,初值爲n;設full是消費者的私有信號量,表示緩衝區中非空單元數,初值爲0。(12分)
生產者: 消費者: begin begin wait(mutex) wait(mutex) wait(avail) wait(full) 送數據到緩衝區某單元 取緩衝區某單元數據 signal(full) signal(avail) signal(mutex) signal(mutex) end end
按題中的互斥方法有可能致使死鎖,例如生產者先拿到操做信號量mutex,但此時緩存區信號量爲full,則會致使生產者沒法進行後續操做且不會釋放信號量mutex,而消費者則始終等待信號量mutex。
改進以下:
生產者: 消費者: begin begin wait(avail) wait(full) wait(mutex) wait(mutex) 送數據到緩衝區某單元 取緩衝區某單元數據 signal(mutex) signal(mutex) signal(full) signal(avail) end end
and信號量能夠理解爲要麼全分配,要麼我都不分配。