Linux下多线程模拟停车场停车
#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 4 typedef 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; }