1. 程式人生 > 實用技巧 >Linux下模擬哲學家就餐,提供死鎖和非死鎖解法

Linux下模擬哲學家就餐,提供死鎖和非死鎖解法

/**
 * every philosopher is in while loop:
 * thinking -> take_forks -> eating -> put_down_forks -> thingking
 * 死鎖:修改N_ROOM為5,開啟take_forks(int id)函式中的sleep(5);
 */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define N 5 // five philosopher
#define T_EAT 5
#define T_THINK 5
#define N_ROOM  4  //同一時間只允許X人用餐
#define left(phi_id) (phi_id+N-1)%N
#define right(phi_id) (phi_id+1)%N

enum { think , hungry , eat  }phi_state[N];
sem_t chopstick[N];
sem_t room;

void thinking(int id){
    sleep(T_THINK);
    printf("philosopher[%d] is thinking....\n", id);
}

void eating(int id){
    sleep(T_EAT);
    printf("philosopher[%d] is eating....\n", id);
}

void take_forks(int id){
    //獲取左右兩邊的筷子
    printf("philosopher[%d] is trying to get left[%d] chopstick.???????\n", id, left(id));
    sem_wait(&chopstick[left(id)]);
    printf("philosopher[%d]  takes left[%d] chopstick.------\n", id, left(id));
    //sleep(5);	//增加死鎖機率
    printf("philosopher[%d] is trying to get right[%d] chopstick.??????\n", id, id);
    sem_wait(&chopstick[id]);
    printf("philosopher[%d]  takes right[%d] chopstick.-----\n", id, id);
}

void put_down_forks(int id){
    printf("philosopher[%d] put_down_forks...vvvvvv\n", id);
    sem_post(&chopstick[left(id)]);
    sem_post(&chopstick[id]);
}

void* philosopher_work(void *arg){
    int id = *(int*)arg;
    printf("philosopher init [%d] \n", id);
    while(1){
        thinking(id);
        sem_wait(&room);
        take_forks(id);
        sem_post(&room);
        eating(id);
        put_down_forks(id);
    }
}

int main(){
    pthread_t phiTid[N];
    int i;
    int err;
    int *id=(int *)malloc(sizeof(int)*N);

    //initilize semaphore
    for (i = 0; i < N; i++)
    {
        if(sem_init(&chopstick[i], 0, 1) != 0)
        {
            printf("init forks error\n");
        }
    }

    sem_init(&room, 0, N_ROOM);

    for(i=0; i < N; ++i){
        id[i] = i;
        err = pthread_create(&phiTid[i], NULL, philosopher_work, (void*)(&id[i])); //這種情況生成的thread id是0,1,2,3,4
        if (err != 0)
            printf("can't create process for reader\n");
    }
    while(1);
    // delete the source of semaphore
    for (i = 0; i < N; i++)
    {
        err = sem_destroy(&chopstick[i]);
        if (err != 0)
        {
            printf("can't destory semaphore\n");
        }
    }
    exit(0);
    return 0;
}