这个问题其实还是挺有意思的
死锁是进程并发执行过程中可能出现的现象,哲学家就餐问题是描述死锁的经典例子。假设有几位哲学家围坐在一张餐桌旁,桌上有吃不尽的食品,每两位哲学家之间摆放着一根筷子,筷子的个数与哲学家的数量相等,每一位哲学家要么思考,要么等待,要么拿起左右两根筷子进餐。本设计假设有五个哲学家和五根筷子,它们的编号都是从0到4。 如果每位哲学家都拿起左边的筷子,就会发生死锁。
程序需要六个线程,主线程用于显示功能描述;五个哲学家线程用于模拟哲学家的活动,即不停地思考、饥饿、进食。相邻的两个哲学家线程需要共享他们中间的同一根筷子,因此对每一根筷子的使用要互斥,用互斥体数组h_mutex_chopsticks来实现。主线程创建五个哲学家线程后要等待所有哲学家结束,用线程句柄数组h_thread来表示五个线程,主线程通过等待这五个线程句柄来实现同步。
直接放代码了,就是申请
#include <windows.h> #include <conio.h> #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <time.h> #include <semaphore.h> #include <stdlib.h> #include <string.h> #include <math.h> pthread_mutex_t chopsticks[5];// 互斥信号量 int just_number[5] = {0, 1, 2, 3, 4};//数字 void *deadlock_philosopher(void *data) { int philosopher_number = *(int *)(data); //int i = 0; for (;;) { srand((unsigned)time(NULL) * (philosopher_number + 1));//随机申请一个数 sleep(0.1);//思考 /*if (i >= 5) {//就5个,多了回到0 i = 0; } else{ i++; }*/ //对一个筷子加锁 printf("%d号哲学家在等待%d号筷子\n",philosopher_number,philosopher_number); pthread_mutex_lock(&chopsticks[philosopher_number]); //sleep(0.1/4); //对旁边的筷子加个锁 printf("%d号哲学家在等待%d号筷子\n",philosopher_number,(1 + philosopher_number) % 5); pthread_mutex_lock(&chopsticks[(1 + philosopher_number) % 5]); printf("%d号哲学家正在吃饭\n\n", philosopher_number); sleep(0.1); printf("%d号哲学家在等待%d号筷子\n",philosopher_number,philosopher_number);//放下筷子进行解锁 pthread_mutex_unlock(&chopsticks[philosopher_number]); printf("%d号哲学家在等待%d号筷子\n",philosopher_number,(1 + philosopher_number) % 5);//对另一根筷子解锁 pthread_mutex_unlock(&chopsticks[(1 + philosopher_number) % 5]); } return 0; } void deadlock() { int i = 0; pthread_t h_thread[5];//声明线程ID,哲学家的编号 printf("\n"); for (i = 0; i < 5; i++) { pthread_mutex_init(&chopsticks[i], NULL);// 5 互斥锁 初始化 }; for (i = 0; i < 5; i++) { pthread_create(&h_thread[i], NULL, deadlock_philosopher, &just_number[i]);//创造线程 }; for (i = 0; i < 5; i++) { pthread_join(h_thread[i], NULL);//等待线程结束, 线程 资源回收函数 } } int main(int argc, char *argv[]) { while (1) { deadlock(); } return 0; }
大概就是这个样子了