死锁生死与饥饿的哲学家

这是使用信号量解决geeksforgeeks餐饮哲学家问题的解决方案:

#include <pthread.h> 
#include <semaphore.h> 
#include <stdio.h> 
#include <unistd.h>

#define N 5 
#define THINKING 2 
#define HUNGRY 1 
#define EATING 0 
#define LEFT (phnum + 4) % N 
#define RIGHT (phnum + 1) % N 

int state[N]; 
int phil[N] = { 0,1,2,3,4 }; 

sem_t mutex; 
sem_t S[N]; 

void test(int phnum) 
{ 
    if (state[phnum] == HUNGRY 
        && state[LEFT] != EATING 
        && state[RIGHT] != EATING) { 
        // state that eating 
        state[phnum] = EATING; 

        sleep(2); 

        printf("Philosopher %d takes fork %d and %d\n",phnum + 1,LEFT + 1,phnum + 1); 

        printf("Philosopher %d is Eating\n",phnum + 1); 

        // sem_post(&S[phnum]) has no effect 
        // during takefork 
        // used to wake up hungry philosophers 
        // during putfork 
        sem_post(&S[phnum]); 
    } 
} 

// take up chopsticks 
void take_fork(int phnum) 
{ 

    sem_wait(&mutex); 

    // state that hungry 
    state[phnum] = HUNGRY; 

    printf("Philosopher %d is Hungry\n",phnum + 1); 

    // eat if neighbours are not eating 
    test(phnum); 

    sem_post(&mutex); 

    // if unable to eat wait to be signalled 
    sem_wait(&S[phnum]); 

    sleep(1); 
} 

// put down chopsticks 
void put_fork(int phnum) 
{ 

    sem_wait(&mutex); 

    // state that thinking 
    state[phnum] = THINKING; 

    printf("Philosopher %d putting fork %d and %d down\n",phnum + 1); 
    printf("Philosopher %d is thinking\n",phnum + 1); 

    test(LEFT); 
    test(RIGHT); 

    sem_post(&mutex); 
} 

void* philospher(void* num) 
{ 

    while (1) { 

        int* i = num; 

        sleep(1); 

        take_fork(*i); 

        sleep(0); 

        put_fork(*i); 
    } 
} 

int main() 
{ 

    int i; 
    pthread_t thread_id[N]; 

    // initialize the mutexes 
    sem_init(&mutex,1); 

    for (i = 0; i < N; i++) 

        sem_init(&S[i],0); 

    for (i = 0; i < N; i++) { 

        // create philosopher processes 
        pthread_create(&thread_id[i],NULL,philospher,&phil[i]); 

        printf("Philosopher %d is thinking\n",i + 1); 
    } 

    for (i = 0; i < N; i++) 

        pthread_join(thread_id[i],NULL); 
} 

https://www.geeksforgeeks.org/dining-philosopher-problem-using-semaphores/

此代码死锁和死机的可能性很小, 我想更改它,使其极有可能出现死锁,活锁或饥饿, 我怎样才能做到这一点?

还有我如何确保该解决方案在100%的情况下(如果可能)不会出现任何这些问题

iCMS 回答:死锁生死与饥饿的哲学家

好吧,首先,我所知的关于餐饮哲学家问题的最佳解决方案是(根据现代操作系统-Tannebaum和Bos的第四版):

#define TRUE 1
#define N 5
#define LEFT (i+N-1)%N
#define RIGHT (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2

typedef int semaphore;
int state[N];
semaphore mutex = 1;
semaphore s[N];

void
philosopher(int i){
  while(TRUE){
    think();
    take_forks(i);
    eat();
    put_forks(i)
  }
}

void
take_forks(int i){
  down(&mutex);
  state[i] = HUNGRY;
  test(i);
  up(&mutex);
  down(&s[i]);
}

void
put_forks(i){
  down(&mutex);
  state[i] = THINKING;
  test(LEFT);
  test(RIGHT);
  up(&mutex);
}

void
test(int i){
  if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING){
    state[i] = EATING;
    up(&s[i]);
  }
}

为简单起见,当然省略了原型和一些功能,但要点是,如果您要创建一个完全不安全的餐饮哲学家,解决方案是这样的:

  #define N 5

  void philosopher(int i){
    while(TRUE){
      think();
      take_fork(i);
      take_fork((i+1)%N);
      eat();
      put_fork(i);
      put_fork((i+1)%N);
    }
  } 

说明: 该程序将很容易产生竞争状态,实际上两个哲学家将使用同一分叉,这是因为我们不使用信号量等待轮到我们吃饭,它也将产生饥饿,因为我们不使用{{1} },检查是否有人已经使用了我们的fork,因此如果您要修改程序以解决此问题,则应删除test()以及使用过信号灯和任何类型测试的所有代码段。

本文链接:https://www.f2er.com/2259394.html

大家都在问