哲学家就餐问题与死锁

程序结构设计程序需要六个线程,主线程用于显示主菜单,接收用户的功能选择;五个哲学家线程用于模拟哲学家的活动,即不停地思考、饥饿、进食。相邻的两个哲学家线程需要共享他们中间的同一根筷子,因此对每一根筷子的使用要互斥,用互斥体数组h_mutex_chopsticks来实现。主线程创建五个哲学家线程后要等待所有哲学家结束,用线程句柄数组h_thread来表示五个线程,主线程通过等待这五个线程句柄来实现同步。算法设计下面给出主要函数的算法描述。(1)deadlock_philosopher函数{
摘要由CSDN通过智能技术生成

程序结构设计
程序需要六个线程,主线程用于显示主菜单,接收用户的功能选择;五个哲学家线程用于模拟哲学家的活动,即不停地思考、饥饿、进食。相邻的两个哲学家线程需要共享他们中间的同一根筷子,因此对每一根筷子的使用要互斥,用互斥体数组h_mutex_chopsticks来实现。主线程创建五个哲学家线程后要等待所有哲学家结束,用线程句柄数组h_thread来表示五个线程,主线程通过等待这五个线程句柄来实现同步。

算法设计
下面给出主要函数的算法描述。

(1)deadlock_philosopher函数
{
   
    while(1){
   
随机等待一段时间;
			提示等待左边筷子;
			申请左边筷子;
			随机等待一段时间;
			提示等待右边筷子;
			申请右边筷子;
			提示正在进餐;
			放下左边筷子;
放下右边筷子;
		}
}

(2)ordered_allocation_philosopher函数
{
   
    while(1){
   
随机等待一段时间;
			提示等待左右两边编号较小的筷子;
			申请编号较小的筷子;
			随机等待一段时间;
			提示等待左右两边编号较大的筷子;
			申请编号较大的筷子;
			提示正在进餐;
			放下编号较小的筷子;
放下编号较大的筷子;
		}
}

(3)pre_allocation_philosopher函数
{
   
    while(1){
   
			提示等待左边筷子;
			提示等待右边筷子;
			同时申请左边和右边两根筷子;
			提示正在进餐;
随机等待一段时间;
			放下左边筷子;
放下右边筷子;
		}
}

(4)deadlock函数
{
   
为每根筷子创建一个互斥信号量;
创建五个可能产生死锁的哲学家线程;
等待五个哲学家线程结束;
}

其他的初始化函数与deadlock()的算法相同,只不过在创建线程时使用不同的线程函数。
在windows中可以用系统调用WaitForMultipleObjects()同时申请两份资源,但是在linux中没有相应的系统调用,因此要在linux下实现资源预分配法,就要自己编写同时申请两根筷子的函数。这需要将哲学家的状态增至三个, 即思考、饥俄、进食,每个哲学家仅在饥俄时才申请筷子,而且同时申请其左右两根筷子,如果此时左右两根子不同时空闲,则哲学家将等待。具体解法如下所示。

#define N 5
    typedef enum{
   thinking, hungry, eating}status;
    status state[N];
    semaphore self[N];
semaphore mutex = 1;

void test(int i)
    {
   
if((state[i] == hungry)&&
      (state[(i-1)%N] != eating)&&
      (state[(i+1)%N] != eating)){
   
          state[i] = eating;
          V(self[i]);
      }
}

void pick_chopsticks(int i)
    {
   
         P(mutex);
         state[i] = hungry;
         test(i);
         V(mutex);
         P(self[i]);
 }

void put_chopsticks(int i)
    {
   
         P(mutex);
         state[i] = thinking;
         test((i-1)%N);
         test((i+1)%N);
         V(mutex);
}

    void philosopher(int i)
    {
   
       while(1){
   
         think();
         pick_chopsticks(i);
         eat();
         put_chopsticks(i);
    }
   
void main
{
   
    int i;
    for(i=0;i<5;i++){
   
state[i] = thingking;
self[i].value = 0;
        }
    }

在上述程序中, 自定义数据类型status用来枚举哲学家的状态,数组state用来存放五个哲学家的状态,由于该数组是全局变量,所以用信号灯变量mutex实现对它的互斥访问。信号量数组self包含五个元素,每个元素的初始值皆为0,当第i号哲学家不具备进食条件时,会将自己阻塞在信号量self[i]上。函数test用于测试i号哲学家是否具备进食的条件。i号哲学家可以进食必须同时满足以下条件:i号哲学家饥饿,左边哲学家不在进食,右边哲学家不在进食。

【linux下的程序代码】
编译命令:

gcc dinning .c –o dinning.o –lcurses –lpthread

程序清单

#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <curses.h>
#include <time.h>
#include <semaphore.h>

#include <string.h>
#define MAX_PHILOSOPHERS 5 
#define ZERO 48  
#define DELAY (rand()%25)/1000

typedef enum {
   thinking,hungry,eating}status;//status用来枚举哲学家的状态
status state[MAX_PHILOSOPHERS];//存放五个哲学家的状态,全局变量

pthread_mutex_t pre_mutex;//用信号灯变量mutex实现对state的互斥访问
sem_t pre_self[MAX_PHILOSOPHERS];//信号量数组self包含五个元素,每个元素的初始值皆为0
pthread_mutex_t h_mutex_chopsticks[MAX_PHILOSOPHERS];//互斥体数组实现对每一根筷子的互斥使用

int thread_number[MAX_PHILOSOPHERS]=
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值