?
#include<stdio.h> #include<string.h> #include<unistd.h> #include<stdlib.h> #include<pthread.h>#define ONE_SECOND 1000000 #define RANGE 10 #define PERIOD 2 #define NUM_THREADS 4typedef struct {int *carpark; //用一個數組來模擬停車場停車位int capacity; //停車場的車輛容量int occupied; //停車場現有的車輛數目int nextin; //下一個進來的車的位置(用carpark數組代表的下標表示)int nextout; //下一個取走的車的停車位置int cars_in; //記錄停車場進入車輛的總和int cars_out; //記錄從停車場開出去的車輛總和pthread_mutex_t lock; //互斥量,保護該結構中的數據被線程互斥的方式使用pthread_cond_t space; //條件變量 描述停車場是否有空位置pthread_cond_t car; //條件變量 描述停車場是否有車pthread_barrier_t bar; //線程屏障 }cp_t;static void initialise(cp_t *cp,int size) {cp->occupied = cp->nextin = cp->nextout = cp->cars_in = cp->cars_out = 0;cp->capacity = size;cp->carpark = (int *)malloc(cp->capacity * sizeof(*cp->carpark));//初始化線程屏障,NUM_THREADS表示等待 NUM_THREADS=4個線程同步執行pthread_barrier_init(&cp->bar,NULL,NUM_THREADS);if(cp->carpark == NULL){perror("malloc()");exit(1);}srand((unsigned int )getpid());pthread_mutex_init(&cp->lock,NULL); //初始化停車場的鎖pthread_cond_init(&cp->space,NULL); //初始化描述停車場是否有空位的條件變量pthread_cond_init(&cp->car,NULL); //初始化描述停車場是否有車的條件變量 }static void* car_in_handler(void* carpark_in) {cp_t *temp;unsigned int seed;temp = (cp_t *)carpark_in;//pthread_barrier_wait 函數表示,線程已完成工作,等到其他線程趕來pthread_barrier_wait(&temp->bar);while(1){//將線程掛起一段時間,模擬車輛到來的隨機性usleep(rand_r(&seed) % ONE_SECOND);pthread_mutex_lock(&temp->lock);//循環等待知道有停車位while(temp->occupied == temp->capacity)pthread_cond_wait(&temp->space,&temp->lock);//插入一輛車,用隨機數標識temp->carpark[temp->nextin] = rand_r(&seed) % RANGE;temp->occupied++;temp->nextin++;temp->nextin %= temp->capacity;temp->cars_in++;//可能有的人在等車可取,發送temp->car條件變量pthread_cond_signal(&temp->car);pthread_mutex_unlock(&temp->lock);}return ((void*)NULL); }static void* car_out_handler(void *carpark_out) {cp_t *temp;unsigned int seed;temp = (cp_t *)carpark_out;pthread_barrier_wait(&temp->bar);for(;;){usleep(rand_r(&seed) % ONE_SECOND);pthread_mutex_lock(&temp->lock);/*獲得鎖后訪問temp->occupied 變量,此時如果車輛數為0 (occupied == 0)pthread_cond_wait 進行的操作就是忙等,釋放鎖(&temp->lock)供其他路線使用知道temp->car條件改變時再次將鎖鎖住*/while(temp->occupied == 0){pthread_cond_wait(&temp->car,&temp->lock);}temp->occupied--;temp->nextout++;temp->nextout %= temp->capacity;temp->cars_out++;pthread_cond_signal(&temp->space);pthread_mutex_unlock(&temp->lock);}return ((void *)NULL); }static void *monitor(void *carpark_in) {cp_t *temp;temp = (cp_t *)carpark_in;for(;;){sleep(PERIOD);pthread_mutex_lock(&temp->lock);printf("Delta:%d\n",temp->cars_in - temp->cars_out - temp->occupied);printf("Number of cars in carpark:%d\n",temp->occupied);pthread_mutex_unlock(&temp->lock);}return ((void *)NULL); }int main(int argc,char **argv) {printf("main version 1.0\n");if(argc != 2){printf("Usage :%s carparksize\n",argv[0]);exit(1);}cp_t outpark;initialise(&outpark,atoi(argv[1])); //初始化停車場數據結構 pthread_t car_in,car_out,m; //定義線程變量 pthread_t car_in2,car_out2;/***創建往停車場停車線程(生成者1)創建從停車場取車線程(消費者1)創建往停車場停車線程(生成者2)創建從停車場取車線程(消費者2)創建用于監控停車場狀況的線程***/pthread_create(&car_in,NULL,car_in_handler,(void*)&outpark);pthread_create(&car_out,NULL,car_out_handler,(void*)&outpark);pthread_create(&car_in2,NULL,car_in_handler,(void*)&outpark);pthread_create(&car_out2,NULL,car_out_handler,(void*)&outpark);pthread_create(&m,NULL,monitor,(void*)&outpark);//pthread_join的第二個參數為NULL,表示不關心線程返回狀態,僅僅等待指定線程的終止 pthread_join(car_in,NULL);pthread_join(car_out,NULL);pthread_join(car_in2,NULL);pthread_join(car_out2,NULL);pthread_join(m,NULL);return 0; }
?