生活随笔
收集整理的這篇文章主要介紹了
Linux 系统应用编程——多线程经典问题(生产者-消费者)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?“生產(chǎn)者——消費(fèi)者”問題是Linux多線程編程中的經(jīng)典問題,主要是利用信號(hào)量處理線程間的同步和互斥問題。
? ? ? ? ?“生產(chǎn)者——消費(fèi)者”問題描述如下:
? ? ? ? ? 有一個(gè)有限緩沖區(qū)(這里用有名管道實(shí)現(xiàn) FIFO 式緩沖區(qū))和兩個(gè)線程:生產(chǎn)者和消費(fèi)者,它們分別不停地把產(chǎn)品放入緩沖區(qū)中拿走產(chǎn)品。一個(gè)生產(chǎn)者在緩沖區(qū)滿的時(shí)候必須等待,一個(gè)消費(fèi)者在緩沖區(qū)空的時(shí)候也不IXUS等待。另外,因?yàn)榫彌_區(qū)是臨界資源,所以生產(chǎn)者和消費(fèi)者之間必須互斥進(jìn)行。它們之間的關(guān)系如下:
這里要求使用有名管道來模擬有限緩沖區(qū),并用信號(hào)量來解決“生產(chǎn)者——消費(fèi)者”問題中的同步和互斥問題。
1、信號(hào)量分析
? ? ? ? 這里使用3個(gè)信號(hào)量,其中兩個(gè)信號(hào)量 avail 和 full 分別用于解決生產(chǎn)者和消費(fèi)者線程之間的互斥問題。其中avail 表示緩沖區(qū)的空單元數(shù),初始值為N;full 表示緩沖區(qū)非空單元數(shù),初始值為 0 ; mutex 是互斥信號(hào)量 ,初始值為 1(當(dāng)然也可以用互斥鎖來實(shí)現(xiàn)互斥操作)。
2、畫出流程圖
3、編寫代碼
? ? ? ? 本實(shí)驗(yàn)的代碼中緩沖區(qū)擁有3個(gè)單元,每個(gè)單元為5個(gè)字節(jié)。為了盡量體現(xiàn)每個(gè)信號(hào)量的意義,在程序中生產(chǎn)過程和消費(fèi)過程是隨機(jī)(采取0~5s 的隨機(jī)事件間隔)進(jìn)行的,而且生產(chǎn)者的速度比消費(fèi)者的速度平均快兩倍左右。生產(chǎn)者一次生產(chǎn)一個(gè)單元的產(chǎn)品(放入hello字符串),消費(fèi)者一次消費(fèi)一個(gè)單元的產(chǎn)品。
[cpp]?view plaincopy
#include?<stdio.h>?? #include?<stdlib.h>?? #include?<string.h>?? #include?<unistd.h>?? #include?<pthread.h>?? #include?<sys/types.h>?? #include?<time.h>?? #include?<fcntl.h>?? #include?<semaphore.h>?? #include?<sys/ipc.h>?? #include?<errno.h>?? #define?MYFIFO?"myfifo"?? #define?BUFFER_SIZE?3?? #define?UNIT_SIZE?5?? #define?RUN_TIME?30?? #define?DELAY_TIME_LEVELS?5.0?? ?? void?*producer(void?*arg);?? void?*customer(void?*arg);?? ?? int?fd;?? time_t?end_time;?? sem_t?mutex,full,avail;?? ?? int?main()?? {?? ????int?ret;?? ????pthread_t?thrd_prd_id,thrd_cst_id;?? ?? ????srand(time(NULL));?? ????end_time?=?time(NULL)?+?RUN_TIME;?? ?? ?????????? ????if((mkfifo(MYFIFO,0644)?<?0)?&&?(errno?!=?EEXIST))?? ????{?? ????????perror("mkfifo?error!");?? ????????exit(-1);?? ????}?? ?? ?????????? ????fd?=?open(MYFIFO,O_RDWR);?? ????if(fd?==?-1)?? ????{?? ????????perror("open?fifo?error");?? ????????exit(-1);?? ????}?? ?? ?????????? ????ret?=?sem_init(&mutex,0,1);?? ?????????? ????ret?+=?sem_init(&avail,0,BUFFER_SIZE);?? ?????? ????ret?+=?sem_init(&full,0,0);?? ?? ????if(ret?!=?0)?? ????{?? ????????perror("sem_init?error");?? ????????exit(-1);?? ????}?? ?? ?????????? ????ret?=?pthread_create(&thrd_prd_id,NULL,producer,NULL);?? ????if(ret?!=?0)?? ????{?? ????????perror("producer?pthread_create?error");?? ????????exit(-1);?? ????}?? ?? ????ret?=?pthread_create(&thrd_cst_id,NULL,customer,NULL);?? ????if(ret?!=?0)?? ????{?? ????????perror("customer?pthread_create?error");?? ????????exit(-1);?? ????}?? ?? ????pthread_join(thrd_prd_id,NULL);?? ????pthread_join(thrd_cst_id,NULL);?? ????close(fd);?? ????unlink(MYFIFO);?? ?? ????return?0;?? }?? ?? void?*producer(void?*arg)??? {?? ????int?real_write;?? ????int?delay_time;?? ?? ????while(time(NULL)?<?end_time)?? ????{?? ????????delay_time?=?(int)(rand()?*?DELAY_TIME_LEVELS/RAND_MAX/2.0)?+?1;?? ????????sleep(delay_time);?? ?? ?????????????????? ????????sem_wait(&avail);?? ????????sem_wait(&mutex);?? ????????printf("\nproducer?have?delayed?%d?seconds\n",delay_time);?? ?? ?????????????????? ????????if((real_write?=?write(fd,"hello",UNIT_SIZE))?==?-1)?? ????????{?? ????????????if(errno?==?EAGAIN)?? ????????????{?? ????????????????printf("The?buffer?is?full,please?wait?for?reading!\n");?? ????????????}?? ????????}?? ????????else?? ????????{?? ????????????printf("producer?writes?%d?bytes?to?the?FIFO\n",real_write);?????????? ????????????printf("Now,the?buffer?left?%d?spaces!\n",avail);?? ????????}?? ?????????????????? ????????sem_post(&full);?? ????????sem_post(&mutex);?? ????}?? ????pthread_exit(NULL);?? }?? ?? void?*customer(void?*arg)??? {?? ????unsigned?char?read_buffer[UNIT_SIZE];?? ????int?real_read;?? ????int?delay_time;?? ?? ????while(time(NULL)?<?end_time)?? ????{?? ????????delay_time?=?(int)(rand()?*?DELAY_TIME_LEVELS/RAND_MAX/2.0)?+?1;?? ????????sleep(delay_time);?? ?? ????????sem_wait(&full);??? ????????sem_wait(&mutex);?? ????????memset(read_buffer,0,UNIT_SIZE);?? ????????printf("\nCustomer?have?delayed?%d?seconds\n",delay_time);?? ?? ????????if((real_read?=?read(fd,read_buffer,UNIT_SIZE))?==?-1)?? ????????{?? ????????????if(errno?==?EAGAIN)?? ????????????{?? ????????????????printf("The?buffer?is?empty,please?wait?for?writing!\n");?? ????????????}?? ????????}?? ????????else?? ????????{?? ????????????printf("customer?reads?%d?bytes?from?the?FIFO\n",real_read);?????????? ????????}?? ?? ????????sem_post(&avail);??? ????????sem_post(&mutex);????????? ????}?? ?? ????pthread_exit(NULL);?? }??
執(zhí)行結(jié)果如下:
[cpp]?view plaincopy
fs@ubuntu:~/qiang/pthread$?./cust_prod??? ?? producer?have?delayed?2?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?2?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?2?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?1?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?1?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?3?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?3?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? producer?have?delayed?1?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?1?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? Customer?have?delayed?1?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?3?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?1?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?2?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?1?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?1?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? producer?have?delayed?1?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?1?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?2?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?1?spaces!?? ?? Customer?have?delayed?3?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? Customer?have?delayed?1?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?3?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? producer?have?delayed?1?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?1?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? Customer?have?delayed?1?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?3?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? ?? Customer?have?delayed?2?seconds?? customer?reads?5?bytes?from?the?FIFO?? ?? producer?have?delayed?2?seconds?? producer?writes?5?bytes?to?the?FIFO?? Now,the?buffer?left?2?spaces!?? fs@ubuntu:~/qiang/pthread$ ?
總結(jié)
以上是生活随笔為你收集整理的Linux 系统应用编程——多线程经典问题(生产者-消费者)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。