生產者和消費者(互斥與同步)。資源用隊列模擬(要上鎖,一個時間只能有一個線程操作隊列)。
m個生產者。拿到鎖,且產品不滿,才能生產。當產品滿,則等待,等待消費者喚醒。當產品由空到不空,通知消費者。n個消費者。拿到鎖,且有產品,才能消費。當產品空,則等待,等待生產者喚醒。當產品由滿到不滿,通知生產者。 生產者條件:隊列不滿消費者條件:隊列不空因此有兩個條件變量。
代碼/************************************************************************* > File Name: main.c > Author: KrisChou > Mail:zhoujx0219@163.com > Created Time: Tue 26 Aug 2014 02:55:01 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <unistd.h>#define CNT 20 /* 最多生產20個產品 *//* 用隊列模擬車間 *//* front和tail初始化均為0,tail是下一個資源生成的下一個數組空間下標 */typedef struct tag{ int s_arr[CNT + 1] ; /* 生產20個產品,必須有21個空間,因為如果空間都裝滿產品,無法區別隊列滿和隊列空 */ int s_front ; int s_tail ;}QUEUE,*pQUEUE ;QUEUE my_que ;/* 資源為空 */int que_empty(pQUEUE pq){ return pq ->s_front == pq -> s_tail ;}/* 資源為滿 */int que_full(pQUEUE pq){ return (pq -> s_tail + 1)% (CNT+1) == pq -> s_front ;}int que_cnt(pQUEUE pq){ return (pq -> s_tail - pq ->s_front + CNT + 1)% (CNT + 1) ;}pthread_mutex_t mutex ;pthread_cond_t cond_PRo, cond_con ;void* pro_handler(void* arg){ pthread_detach(pthread_self()); while(1) { pthread_mutex_lock(&mutex) ; while(que_full(&my_que)) { pthread_cond_wait(&cond_pro, &mutex); } my_que.s_arr[my_que.s_tail ] = rand() % 1000 ; my_que.s_tail = (my_que.s_tail + 1)% (CNT + 1) ; if(que_cnt(&my_que) == 1) { pthread_cond_broadcast(&cond_con); } printf("produce a product, total num : %d /n", que_cnt(&my_que)); pthread_mutex_unlock(&mutex); sleep(rand()%3 + 1); }}void* con_handler(void* arg){ pthread_detach(pthread_self()); while(1) { pthread_mutex_lock(&mutex); while(que_empty(&my_que)) { pthread_cond_wait(&cond_con, &mutex); } my_que.s_front = (my_que.s_front + 1) % (CNT + 1) ; if(que_cnt(&my_que) == CNT - 1) { /*由于我們的主線程是等消費者線程創建完之后,再創建生產者線程, 因此一開始所有消費者線程都會掛起,在條件變量cond_pro的隊列里排隊 因此需要用broadcast通知所有消費者線程。 不然一次就通知一個生產者線程,就此消費者線程會搶鎖。 當然,如果一開始主線程先創建生產者線程,再創建消費者線程, 由于生產者線程不會全部阻塞,因此可以使用signal來喚醒一個 */ pthread_cond_broadcast(&cond_pro); } printf("consume a product, total num: %d /n", que_cnt(&my_que)); pthread_mutex_unlock(&mutex); sleep(rand()%3 + 1); }}int main(int argc, char* argv[])//exe pro_num con_num{ int con_cnt , pro_cnt ; my_que.s_front = 0 ; my_que.s_tail = 0 ; pro_cnt = atoi(argv[1]) ; con_cnt = atoi(argv[2]) ; srand(getpid()); pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond_pro, NULL); pthread_cond_init(&cond_con, NULL); pthread_t* arr = (pthread_t*)calloc(con_cnt + pro_cnt, sizeof(pthread_t)); int index = 0 ; while(con_cnt > 0) { pthread_create(arr + index , NULL, con_handler, NULL); index ++ ; con_cnt -- ; } sleep(5); while(pro_cnt > 0) { pthread_create(arr + index , NULL, pro_handler, NULL); index ++ ; pro_cnt -- ; } while(1) ; pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond_pro); pthread_cond_destroy(&cond_con); return 0 ;}Makefile
main:main.c gcc -o $@ $< -lpthread
新聞熱點
疑難解答