生活随笔
收集整理的這篇文章主要介紹了
Linux 系统应用编程——多线程经典问题(生产者-消费者)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?“生產者——消費者”問題是Linux多線程編程中的經典問題,主要是利用信號量處理線程間的同步和互斥問題。
? ? ? ? ?“生產者——消費者”問題描述如下:
? ? ? ? ? 有一個有限緩沖區(這里用有名管道實現 FIFO 式緩沖區)和兩個線程:生產者和消費者,它們分別不停地把產品放入緩沖區中拿走產品。一個生產者在緩沖區滿的時候必須等待,一個消費者在緩沖區空的時候也不IXUS等待。另外,因為緩沖區是臨界資源,所以生產者和消費者之間必須互斥進行。它們之間的關系如下:
這里要求使用有名管道來模擬有限緩沖區,并用信號量來解決“生產者——消費者”問題中的同步和互斥問題。
1、信號量分析
? ? ? ? 這里使用3個信號量,其中兩個信號量 avail 和 full 分別用于解決生產者和消費者線程之間的互斥問題。其中avail 表示緩沖區的空單元數,初始值為N;full 表示緩沖區非空單元數,初始值為 0 ; mutex 是互斥信號量 ,初始值為 1(當然也可以用互斥鎖來實現互斥操作)。
2、畫出流程圖
3、編寫代碼
? ? ? ? 本實驗的代碼中緩沖區擁有3個單元,每個單元為5個字節。為了盡量體現每個信號量的意義,在程序中生產過程和消費過程是隨機(采取0~5s 的隨機事件間隔)進行的,而且生產者的速度比消費者的速度平均快兩倍左右。生產者一次生產一個單元的產品(放入hello字符串),消費者一次消費一個單元的產品。
[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);?? }??
執行結果如下:
[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$ ?
總結
以上是生活随笔為你收集整理的Linux 系统应用编程——多线程经典问题(生产者-消费者)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。