各位看官們,大家好,上一回中咱們說的是生產者與消費者問題的例子,這一回咱們繼續說該例子。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
我們在上一回中介紹了生產者與消費者問題,並且給出了該問題的解決思路和偽代碼。我們在今天的章回中將把偽代碼轉換為C語言代碼,也就是說通過具體的代碼實現生產者與消費者問題。
詳細的實現步驟如下:
1.自己定義信號量聯合類型和共享內存結構體類型; 2.使用程序中main的參數:-p和-c分別表示生產者和消費者進程;以上步驟是生產者和消費者共同使用的步驟,下面分別列出生產者和消費者各自的實現步驟。
生產者的實現步驟:
消費者的實現步驟:
1.在消費中獲取已經在生產者中創建的信號量; 2.在消費者中獲取已經在生產者中創建的共享內存,並且把共享內存的地址鏈接到消費者進程空間中; 3.對信號量進行P操作; 4.判斷池子中產品的數量是否大於零;如果大於零,那麼進入下一步,否則等待生產者生產產品; 5.消費者從池子中取走一個產品;然後把產品的數量減少一; 6.對信號量進行V操作; 7.重復步驟3到6,直到池子中沒有產品為止; 8.把共享內存的地址鏈接從消費者地址空間中斷開;看官們,正文中就不寫代碼了,詳細的代碼放到了我的資源中,大家可以下載使用。
在代碼中,我們封裝了信號量的P/V操作,使代碼更加簡單一些。
我們對生產者生產產品和消費者取走產品的動作進行了延時,主要是為了方便觀看程序運行結果,進而更好地演示生產者與消費者問題 ;其中對消費者和生產者的延時可以自己控制,代碼中對消費者的延時是生產者的延時的一半。
另外,池子的大小也是可以自己定義的,代碼中池子的大小為8,可以容納8個int類型的變量。
我們在代碼中使用共享內存這種方式進行生產者進程和消費者進程之間的通信,大家可以使用其它進程間的通信方式。比如:管道,FIFO以及消息隊列。
有看官提問說,能不能使用一個全局變量和全局數組代替共享內存。我的回答是不能,因為全局變量只是在一個進程中是全局的,而我們使用了兩個進程,這顯然不行。說的更加直接點,如果生產者進程更新了全局變量和全局數組,那麼消費者進程根本看不到生產者更新的內容,在消費者看來它們沒有變,或者說產品數量為零而且池子也是空的。
下面是程序的運行結果,請大家參考:
$ ./a -p & //在後台運行編譯後的程序,使用參數-p啟動生產者進程
[1] 3562 //生產者進程已經啟動,PID為3562
$ [pid: 3562 ] producer is running
producer count: 0 //生產者生產產品前,產品數量為空,池子裡沒有任何產品
produce data. count:1,data:1
producer count: 1
produce data. count:2,data:2
producer count: 2
produce data. count:3,data:3 //生產者生產了3個產品,並且存放到了池子中
./a -c //在前台運行編譯後的程序,使用參數-c啟動消費者進程
[pid: 3563 ] customer is running //生產者進程已經啟動,PID為3563
customer count: 3 //在消費者取走產品前,產品數量為3,池子裡有3個產品
get data. count:3,data:3 //消費者取走1個產品
producer count: 2
produce data. count:3,data:3 //生產者生產了1個產品
customer count: 3
get data. count:3,data:3
customer count: 2
get data. count:2,data:2 //消費者又取走了2個產品
producer count: 1
produce data. count:2,data:2 //生產者又生產了1個產品
customer count: 2
get data. count:2,data:2
customer count: 1
get data. count:1,data:1 //消費者取走2個產品
producer count: 0
produce data. count:1,data:1 //生產者又生產了1個產品
customer count: 1
get data. count:1,data:1
customer count: 0
the buf is empty //消費者取走1個產品,池子中沒有產品了
[pid: 3563 ] customer running finished //消費者進程結束
$ producer count: 0
produce data. count:1,data:1
producer count: 1
produce data. count:2,data:2
producer count: 2
produce data. count:3,data:3
producer count: 3
produce data. count:4,data:4
producer count: 4
produce data. count:5,data:5
producer count: 5
produce data. count:6,data:6
producer count: 6
produce data. count:7,data:7
producer count: 7
produce data. count:8,data:8
producer count: 8
the buf is full //生產者連續生產了8 個產品,池子已經満了
[pid: 3562 ] producer running finished //生產者結束
//輸入回車鍵,返回到終端中
[1]+ Done
從程序的運行結果中可以看到,生產者進程和消費進程交替運行,一個進程向池子中添加產品,另外一個進程從池子中取走產品。但是無論如何,池子中產品的數量在生產者和消費者看來都是一致的,這受益於信號量對生產者進程和消費者進程進行了同步操作。此外,我們對代碼做了處理,當池子已經滿了,生產者便停止生產產品,同時結束生產者進程,而不是一直等待消費者從池子中取走產品。當池子中沒有產品時,消費者不再從池子中取走產品,同時結束消費者進程,而不是一直等待生產者生產產品。不然我們的程序就永遠也不能結束了。
各位看官,關於生產者與消費者問題的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。