开小车
来源:互联网 发布:腾讯数据合作公司 编辑:程序博客网 时间: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
- 开小车
- ---------------小车
- 小车
- 开小车后的感言
- 51单片机智能小车开<一>
- 自平衡小车开源程序(向zlstone致敬)
- 无线小车
- 机器小车
- 小车问题
- arduino小车
- STM32小车
- arduino小车
- 小车问题
- arduino小车
- 遥控小车
- 智能小车
- 小车问题
- 【Ardunio小车】智能小车组装
- 自定义View——canvas画曲线图表
- 大数据面试题分析
- BZOJ 1142: [POI2009]Tab 模拟
- ListView实现每行显示两个item(假)
- strip命令去掉符号信息和调试信息
- 开小车
- 116. Populating Next Right Pointers in Each Node
- javascript之第四章
- Scala课堂-6-高级类型
- **KMP算法 Problem A. cal 2016/11/12 字符串 c++
- Leetcode-264. Ugly Number II
- OAuth的机制原理讲解及开发流程
- Android之selector的使用
- 问题分析报告--在压力场景下OS在某种硬件环境下的性能可能会下降90%的问题