【问题标题】:dining philosophers with deadlock livelock and starvation与死锁活锁和饥饿的哲学家一起吃饭
【发布时间】:2020-09-14 21:31:01
【问题描述】:

这是 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, LEFT + 1, 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, 0, 1); 

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

        sem_init(&S[i], 0, 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%(如果可能)不会出现任何这些问题

【问题讨论】:

    标签: c operating-system mutex semaphore dining-philosopher


    【解决方案1】:

    好的,首先,我所知道的哲学家就餐问题的最佳解决方案是这个(来自现代操作系统 - Tannebaum 和 Bos 的第 4 版):

    #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);
        }
      } 
    

    解释: 这个程序很容易产生竞争条件,事实上两个哲学家会使用同一个叉子,这是因为我们不使用信号量等待轮到我们吃饭,它也会产生饥饿,因为我们不使用test()检查是否有人已经在使用我们的 fork,所以如果你想修改你的程序以解决这个问题,你应该删除 test() 以及你使用信号量和任何类型的测试的所有代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      • 2021-06-25
      • 2014-03-13
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      相关资源
      最近更新 更多