开小车

来源:互联网 发布:腾讯数据合作公司 编辑:程序博客网 时间:2024/04/28 03:01
#include <stdio.h>     #include <stdlib.h>#include <pthread.h> #include <unistd.h>   #include <string.h>    #define MAX 100  #define SLEEP_TIME 2000//四个方向的宏定义,为了方便数组使用#define N 0#define E 1#define S 2#define W 3       //四个路口的通行条件和配套锁 pthread_cond_t cond[4]; pthread_mutex_t cond_mutex[4];  //四个方向上等待队列的车向前的条件和配套锁pthread_cond_t first[4];pthread_mutex_t first_mutex[4];    //死锁发生的条件和配套锁pthread_cond_t cond_deadlock;pthread_mutex_t cond_deadlock_mutex;  //四个路口的资源(其实这个变量好像并不用,first和source的作用是重复的)pthread_mutex_t source[4];  int dir; //标志引发死锁的车的方向int size=0; //车辆总数  int cross_car_num=0; //十字路口处的车辆数(不包括等待队列)pthread_mutex_t cross_car_num_mutex; //cross_car_num的访问锁int current[4]; //目前每个方向上要过路口的车的idint is_car[4]; //标志每个方向上是否有车要过路口int deadlock_flag=0; //标志当前是否处于死锁或者解死锁状态     pthread_t car[MAX]; //所有车辆线程 pthread_t check; //死锁检测线程pthread_t thread_id[4][MAX]; //每个方向的线程号int car_id[4][MAX]; //每个方向的车辆号int front[4]={0}; //每个方向车辆队列的头指针  int rear[4]={0}; //每个方向车辆队列的尾指针    int count[4]={0}; //每个方向车辆数//把一个车辆放入其方向上的等待队列void push(int dir, int cid) {    count[dir]++;      rear[dir] = (rear[dir] + 1) % MAX;      car_id[dir][rear[dir]] = cid;  }  //把一个车辆移除其方向上的等待队列并返回下一车辆号int pop(int dir) {    count[dir]--;      front[dir] = (front[dir] + 1) % MAX;      return car_id[dir][front[dir]]; }     //初始化条件和锁void initialize(){    int i;    pthread_cond_init(&cond_deadlock, NULL);    pthread_mutex_init(&cond_deadlock_mutex, NULL);    for(i=0;i<4;i++){        pthread_cond_init(&cond[i], NULL);        pthread_mutex_init(&cond_mutex[i], NULL);        pthread_cond_init(&first[i], NULL);        pthread_mutex_init(&first_mutex[i], NULL);        pthread_mutex_init(&source[i], NULL);    }         pthread_mutex_init(&cross_car_num_mutex, NULL);   }//让这个方向的等待队列的车向前void call_next(int dir)  {      if (count[dir]>0) {        current[dir] = pop(dir); //移除前一辆车并得到当前队首        pthread_mutex_lock(&first_mutex[dir]);          pthread_cond_signal(&first[dir]); //释放向前信号        pthread_mutex_unlock(&first_mutex[dir]);      }  }  //让所有方向的等待队列的车向前 void call_next_all()  {     int i;     for(i=0;i<4;i++)        call_next(i);}  //从北边来的车的线程void *car_from_north(void *arg) {      usleep(SLEEP_TIME);    //printf("car from North creates\n");    //现在在等待队列中,等待向前信号     pthread_mutex_lock(&first_mutex[N]);      pthread_cond_wait(&first[N], &first_mutex[N]);      pthread_mutex_unlock(&first_mutex[N]);          //变成第一个啦    //printf("car from North first\n");     is_car[N] = 1; //设置这个路口有车的标志        //要求这个方向过路口的资源    pthread_mutex_lock(&source[N]);    pthread_mutex_lock(&cross_car_num_mutex);    cross_car_num++; //路口车辆数加一    printf("car %d from North arrives at crossing\n", current[N]);      usleep(SLEEP_TIME);     if (cross_car_num == 4) { //如果路口车辆数达到4就会死锁了        //printf("north test deadlock\n");        pthread_mutex_unlock(&cross_car_num_mutex);        //告诉死锁检测线程死锁发生了        pthread_mutex_lock(&cond_deadlock_mutex);        dir = N;  //记录下这个方向,为了让死锁检测进程知道是哪个方向最后引发了死锁,来决定让哪个方向的车先走                    //这个变量不用自己设一个锁,因为它只会在通知死锁的时候被修改,所以和通知死锁的锁用同一个锁就可以了        pthread_cond_signal(&cond_deadlock);         pthread_mutex_unlock(&cond_deadlock_mutex);         //等待被死锁调度进程或者其他车辆唤醒        pthread_mutex_lock(&cond_mutex[N]);          pthread_cond_wait(&cond[N], &cond_mutex[N]);         pthread_mutex_unlock(&cond_mutex[N]);         //usleep(SLEEP_TIME);         //释放该方向路口资源         pthread_mutex_unlock(&source[N]);          printf("car %d from North leaves at crossing\n", current[N]);          is_car[N] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        deadlock_flag=0; //设置死锁已解决的标志        cross_car_num--; //路口车辆数减一        call_next_all(); //根据死锁检测进程的机制,引发死锁的车一定死解一轮死锁中最后一个走的,所以它要唤醒四个路口的等待队列的车向前        pthread_mutex_unlock(&cross_car_num_mutex);          //usleep(SLEEP_TIME);          return NULL;      }        else if (is_car[W]==1) {  //如果右边有车        //  printf("a car on south's right\n");        pthread_mutex_unlock(&cross_car_num_mutex);          //等待右边的车唤醒自己        pthread_mutex_lock(&cond_mutex[N]);          pthread_cond_wait(&cond[N], &cond_mutex[N]);         pthread_mutex_unlock(&cond_mutex[N]);        //usleep(SLEEP_TIME);          //释放该方向路口资源         pthread_mutex_unlock(&source[N]);          printf("car %d from North leaves at crossing\n", current[N]);          is_car[N] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--; //路口车辆数减一        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[E]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME);        if(!deadlock_flag){            call_next(N);        }        return NULL;    }    else{  //如果没什么事我就先走了        //usleep(SLEEP_TIME);          pthread_mutex_unlock(&cross_car_num_mutex);        //释放该方向路口资源        pthread_mutex_unlock(&source[N]);          printf("car %d from North leaves at crossing\n", current[N]);          is_car[N] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--; //路口车辆数减一        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[E]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME);         if(!deadlock_flag){            call_next(N);        }        return NULL;    }  } //从东边来的车的线程void *car_from_east(void *arg) {    usleep(SLEEP_TIME);    //printf("car from East creates\n");      //现在在等待队列中,等待向前信号      pthread_mutex_lock(&first_mutex[E]);      pthread_cond_wait(&first[E], &first_mutex[E]);      pthread_mutex_unlock(&first_mutex[E]);        //变成第一个啦    //printf("car from East first\n");     is_car[E] = 1;          //要求这个方向过路口的资源    pthread_mutex_lock(&source[E]);    pthread_mutex_lock(&cross_car_num_mutex);    cross_car_num++; //路口车辆数加一    printf("car %d from East arrives at crossing\n", current[E]);    usleep(SLEEP_TIME);       if (cross_car_num == 4) { //如果路口车辆数达到4就会死锁了         //printf("east test deadlock\n");        pthread_mutex_unlock(&cross_car_num_mutex);        //告诉死锁检测线程死锁发生了        pthread_mutex_lock(&cond_deadlock_mutex);        dir = E;  //记录下这个方向,为了让死锁检测进程知道是哪个方向最后引发了死锁,来决定让哪个方向的车先走                    //这个变量不用自己设一个锁,因为它只会在通知死锁的时候被修改,所以和通知死锁的锁用同一个锁就可以了        pthread_cond_signal(&cond_deadlock);         pthread_mutex_unlock(&cond_deadlock_mutex);         //等待被死锁调度进程或者其他车辆唤醒        pthread_mutex_lock(&cond_mutex[E]);          pthread_cond_wait(&cond[E], &cond_mutex[E]);         pthread_mutex_unlock(&cond_mutex[E]);         //usleep(SLEEP_TIME);          //释放该方向路口资源        pthread_mutex_unlock(&source[E]);          printf("car %d from East leaves at crossing\n", current[E]);          is_car[E] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        deadlock_flag=0; //设置死锁已解决的标志        cross_car_num--; //路口车辆数减一        call_next_all();  //根据死锁检测进程的机制,引发死锁的车一定死解一轮死锁中最后一个走的,所以它要唤醒四个路口的等待队列的车向前        pthread_mutex_unlock(&cross_car_num_mutex);          //usleep(SLEEP_TIME);          return NULL;      }        else if (is_car[N]==1) {  //如果右边有车        //  printf("a car on south's right\n");         pthread_mutex_unlock(&cross_car_num_mutex);         //等待右边的车唤醒自己        pthread_mutex_lock(&cond_mutex[E]);          pthread_cond_wait(&cond[E], &cond_mutex[E]);         pthread_mutex_unlock(&cond_mutex[E]);        //usleep(SLEEP_TIME);          //释放该方向路口资源         pthread_mutex_unlock(&source[E]);          printf("car %d from East leaves at crossing\n", current[E]);          is_car[E] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--; //路口车辆数减一        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[S]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME); 这个sleep很可能是需要的        if(!deadlock_flag){            call_next(E);        }        return NULL;    }    else{  //如果没什么事我就先走了        //usleep(SLEEP_TIME);          pthread_mutex_unlock(&cross_car_num_mutex);        //释放该方向路口资源        pthread_mutex_unlock(&source[E]);          printf("car %d from East leaves at crossing\n", current[E]);          is_car[E] = 0;        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--;        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[S]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME); 这个sleep很可能是需要的        if(!deadlock_flag){            call_next(E);        }        return NULL;    }  }//从南边来的车的线程void *car_from_south(void *arg) {      usleep(SLEEP_TIME);    //printf("car from South creates\n");    //现在在等待队列中,还不是第一个可以走的      pthread_mutex_lock(&first_mutex[S]);      pthread_cond_wait(&first[S], &first_mutex[S]);      pthread_mutex_unlock(&first_mutex[S]);        //变成第一个啦     //printf("car from South first\n");    is_car[S] = 1;          //要求这个方向过路口的资源    pthread_mutex_lock(&source[S]);    pthread_mutex_lock(&cross_car_num_mutex);    cross_car_num++; //路口车辆数加一    printf("car %d from South arrives at crossing\n", current[S]);     usleep(SLEEP_TIME);      if (cross_car_num == 4) { //如果路口车辆数达到4就会死锁了          //printf("south test deadlock\n");        pthread_mutex_unlock(&cross_car_num_mutex);        //告诉死锁检测线程死锁发生了        pthread_mutex_lock(&cond_deadlock_mutex);        dir = S;  //记录下这个方向,为了让死锁检测进程知道是哪个方向最后引发了死锁,来决定让哪个方向的车先走                    //这个变量不用自己设一个锁,因为它只会在通知死锁的时候被修改,所以和通知死锁的锁用同一个锁就可以了        pthread_cond_signal(&cond_deadlock);         pthread_mutex_unlock(&cond_deadlock_mutex);         //等待被死锁调度进程或者其他车辆唤醒        pthread_mutex_lock(&cond_mutex[S]);          pthread_cond_wait(&cond[S], &cond_mutex[S]);         pthread_mutex_unlock(&cond_mutex[S]);         //usleep(SLEEP_TIME);         //释放该方向路口资源          pthread_mutex_unlock(&source[S]);          printf("car %d from South leaves at crossing\n", current[S]);          is_car[S] = 0; //设置这个路口无车的标志          pthread_mutex_lock(&cross_car_num_mutex);        deadlock_flag=0; //设置死锁已解决的标志        cross_car_num--; //路口车辆数减一        call_next_all(); //如果自己是死锁解完的最后一辆车,那么唤醒四个路口的等待队列的车向前        pthread_mutex_unlock(&cross_car_num_mutex);          //usleep(SLEEP_TIME);          return NULL;      }        else if (is_car[E]==1) {  //如果右边有车        pthread_mutex_unlock(&cross_car_num_mutex);        //  printf("a car on south's right\n");          //等待右边的车唤醒自己        pthread_mutex_lock(&cond_mutex[S]);          pthread_cond_wait(&cond[S], &cond_mutex[S]);         pthread_mutex_unlock(&cond_mutex[S]);        //usleep(SLEEP_TIME);        //释放该方向路口资源           pthread_mutex_unlock(&source[S]);          printf("car %d from South leaves at crossing\n", current[S]);          is_car[S] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--; //路口车辆数减一        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[W]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME); 这个sleep很可能是需要的        if(!deadlock_flag){            call_next(S);        }        return NULL;    }    else{  //如果没什么事我就先走了        pthread_mutex_unlock(&cross_car_num_mutex);        //usleep(SLEEP_TIME);        //释放该方向路口资源          pthread_mutex_unlock(&source[S]);          printf("car %d from South leaves at crossing\n", current[S]);          is_car[S] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--; //路口车辆数减一        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[W]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME); 这个sleep很可能是需要的        if(!deadlock_flag){            call_next(S);        }        return NULL;    }  }  //从西边来的车的线程void *car_from_west(void *arg) {      usleep(SLEEP_TIME);    //printf("car from West creates\n");    //现在在等待队列中,还不是第一个可以走的      pthread_mutex_lock(&first_mutex[W]);      pthread_cond_wait(&first[W], &first_mutex[W]);      pthread_mutex_unlock(&first_mutex[W]);        //变成第一个啦     //printf("car from West first\n");    is_car[W] = 1;          //要求这个方向过路口的资源    pthread_mutex_lock(&source[W]);    pthread_mutex_lock(&cross_car_num_mutex);    cross_car_num++;       printf("car %d from West arrives at crossing\n", current[W]);     usleep(SLEEP_TIME);      if (cross_car_num == 4) { //如果路口车辆数达到4就会死锁了          //printf("west test deadlock\n");        pthread_mutex_unlock(&cross_car_num_mutex);        //告诉死锁检测线程死锁发生了        pthread_mutex_lock(&cond_deadlock_mutex);        dir = W;  //记录下这个方向,为了让死锁检测进程知道是哪个方向最后引发了死锁,来决定让哪个方向的车先走                    //这个变量不用自己设一个锁,因为它只会在通知死锁的时候被修改,所以和通知死锁的锁用同一个锁就可以了        pthread_cond_signal(&cond_deadlock);         pthread_mutex_unlock(&cond_deadlock_mutex);         //等待被死锁调度进程或者其他车辆唤醒        pthread_mutex_lock(&cond_mutex[W]);          pthread_cond_wait(&cond[W], &cond_mutex[W]);         pthread_mutex_unlock(&cond_mutex[W]);         //usleep(SLEEP_TIME);          pthread_mutex_unlock(&source[W]);          printf("car %d from West leaves at crossing\n", current[W]);          is_car[W] = 0; //设置这个路口无车的标志          pthread_mutex_lock(&cross_car_num_mutex);        deadlock_flag=0; //设置死锁已解决的标志        cross_car_num--; //路口车辆数减一        call_next_all(); //如果自己是死锁解完的最后一辆车,那么唤醒四个路口的等待队列的车向前        pthread_mutex_unlock(&cross_car_num_mutex);          //usleep(SLEEP_TIME);          return NULL;      }        else if (is_car[S]==1) {  //如果右边有车        //  printf("a car on south's right\n");          pthread_mutex_unlock(&cross_car_num_mutex);        //等待右边的车唤醒自己        pthread_mutex_lock(&cond_mutex[W]);          pthread_cond_wait(&cond[W], &cond_mutex[W]);         pthread_mutex_unlock(&cond_mutex[W]);         //usleep(SLEEP_TIME);          //释放该方向路口资源        pthread_mutex_unlock(&source[W]);          printf("car %d from West leaves at crossing\n", current[W]);          is_car[W] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--; //路口车辆数减一        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[N]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME); 这个sleep很可能是需要的        if(!deadlock_flag){            call_next(W);        }        return NULL;    }    else{  //如果没什么事我就先走了        pthread_mutex_unlock(&cross_car_num_mutex);        //usleep(SLEEP_TIME);          //释放该方向路口资源        pthread_mutex_unlock(&source[W]);          printf("car %d from West leaves at crossing\n", current[W]);          is_car[W] = 0; //设置这个路口无车的标志        pthread_mutex_lock(&cross_car_num_mutex);        cross_car_num--; //路口车辆数减一        pthread_mutex_unlock(&cross_car_num_mutex);        //如果左边有车,告诉左边的车可以走了        //(这一句不用加判断没关系,因为signal在wait之前执行的话不起作用)        pthread_cond_signal(&cond[N]);        //如果不是在死锁状态,让自己方向的下一辆车上来        //usleep(SLEEP_TIME); 这个sleep很可能是需要的        if(!deadlock_flag){            call_next(W);        }        return NULL;    }  }    void *check_dead_lock(void *arg) {      usleep(SLEEP_TIME);    //printf("check_dead_lock creates\n");    usleep(2*SLEEP_TIME); //等所有线程都创建完(就是所有车都开到路口等了)    call_next_all(); //召唤四个方向等待队列的车向前      while (1) {          //等待死锁进程被触发        pthread_mutex_lock(&cond_deadlock_mutex);           pthread_cond_wait(&cond_deadlock, &cond_deadlock_mutex);        pthread_mutex_unlock(&cond_deadlock_mutex);         deadlock_flag=1; //标志死锁状态        //printf("DEADLOCK: %d ",dir); //测试用        //发一个信号让一个方向的车先走(让引发死锁的车的左边的车先走)         switch (dir) {              case N: {                //printf(" East ");                 printf("DEADLOCK: car jam detected, signalling East to go\n");                pthread_mutex_lock(&cond_mutex[E]);                pthread_cond_signal(&cond[E]);                 pthread_mutex_unlock(&cond_mutex[E]);                break;             }   //如果引发死锁的是N,让E先走            case E: {                printf("DEADLOCK: car jam detected, signalling South to go\n");                pthread_mutex_lock(&cond_mutex[S]);                 pthread_cond_signal(&cond[S]);                pthread_mutex_unlock(&cond_mutex[S]);                  break;             }   //如果引发死锁的是N,让E先走             case W: {                printf("DEADLOCK: car jam detected, signalling North to go\n");                pthread_mutex_lock(&cond_mutex[N]);                 pthread_cond_signal(&cond[N]);                 pthread_mutex_unlock(&cond_mutex[N]);                 break;             }   //如果引发死锁的是N,让E先走             case S: {                printf("DEADLOCK: car jam detected, signalling West to go\n");                pthread_mutex_lock(&cond_mutex[W]);                 pthread_cond_signal(&cond[W]);                pthread_mutex_unlock(&cond_mutex[W]);                  break;             }   //如果引发死锁的是N,让E先走         }        }  }  void thread_wait(){    int i;    usleep(SLEEP_TIME);    for (i = 0; i<size; i++) {          pthread_join(car[i], NULL);      }  //    pthread_join(check, NULL); }  int main() {      initialize(); //初始化    int num[100];    char s[100];     int i;     scanf("%s", s);  //读取输入    int len = strlen(s);       for (i = 0; i<len; i++) num[i] = i + 1;    //创建车辆线程    for (i = 0; i<len; i++) {          switch (s[i]) {          case 'w': {              is_car[W] = 1;              push(W,num[i]);               pthread_create(&thread_id[W][rear[W]], NULL, car_from_west, NULL);              car[size++] = thread_id[W][rear[W]];             break;          }          case 'e': {              is_car[E] = 1;              push(E,num[i]);              pthread_create(&thread_id[E][rear[E]], NULL, car_from_east, NULL);            car[size++] = thread_id[E][rear[E]];                break;          }          case 's': {              is_car[S] = 1;              push(S,num[i]);              pthread_create(&thread_id[S][rear[S]], NULL, car_from_south, NULL);            car[size++] = thread_id[S][rear[S]];                           break;          }          case 'n': {              is_car[N] = 1;              push(N,num[i]);              pthread_create(&thread_id[N][rear[N]], NULL, car_from_north, NULL);             car[size] = thread_id[N][rear[N]];               size++;            break;          }          }      }        //创建死锁检测线程    pthread_create(&check, NULL, check_dead_lock, NULL);         //等待进程结束     thread_wait();}  

0 0
原创粉丝点击