Linux程式設計:程式同步問題之哲學家就餐問題

KoalaZB發表於2016-12-11

哲學家就餐問題描述

5個哲學家用一生的時間吃飯和思考。他們共用一張圓桌,每人都有一張椅子,桌上放著5支筷子。每個哲學家感到飢餓時,會試圖拿起左右的兩隻筷子,每位哲學家每次只能拿起一隻筷子。當每位哲學家同時有兩支筷子的時候,他可以吃飯。當他吃完後,他會放下筷子,並開始思考。
我們需要保證不會出現哲學家餓死的情況發生。這裡寫圖片描述

此博文采用以下兩種方法解決哲學家就餐問題:

  • 要求每位哲學家同時拿起兩隻筷子。
  • 要求座位號為奇數的哲學家先拿左手的筷子,偶數的哲學家先拿右手的筷子。

完整程式碼如下(僅供參考):

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
#define Phi_Number 5

pthread_mutex_t chopstick[5] ;  

void *solve1(void *arg)  
{  
        int phi = *(int *)arg;  
        int left,right; 
        switch (phi)
    {  
        case 1:  
            left = 5;  
            right = 1;  
            break;  
        case 2:  
            left = 1;  
            right = 2;  
            break;  
        case 3:  
            left = 2;  
            right = 3;  
            break;  
        case 4:  
            left = 3;  
            right = 4;  
            break;  
        case 5:  
            left = 4;  
            right = 5;  
            break; 
    }  

    while(1)
    {  
        printf("Philosopher %d is thiking !\n",phi);
        sleep(1); // thinking
        pthread_mutex_lock(&chopstick[left]); // Ruquest left chopstick     
        time_t timep11;
        time (&timep11);
        printf("Philosopher %d takes left chopstick %d at %s",phi,left,asctime(gmtime(&timep11)));

        if (pthread_mutex_trylock(&chopstick[right]))//return 0 if success
        {    
                pthread_mutex_unlock(&chopstick[left]); // Release left chopstick 
            printf("Philosopher %d release left chopstick %d\n", phi, left);  
                continue;  
        }  
        time_t timep1;
        time (&timep1);
        printf("Philosopher %d takes right chopstick %d at %s", phi, right,asctime(gmtime(&timep1))); 
        printf("!!!!!!!!!!!!!!!!!!!!!Philosopher %d is eating~<>_<>~.\n",phi);  
        sleep(3); // eating
        pthread_mutex_unlock(&chopstick[left]); // Release left chopstick 
        printf("Philosopher %d release left chopstick %d\n", phi, left);  
        pthread_mutex_unlock(&chopstick[right]); //  Release right chopstick 
        printf("Philosopher %d release right chopstick %d\n", phi, right);  
        pthread_exit(0);

        }  
}  

void *solve2(void *arg)  
{  
        int phi = *(int *)arg;  
        int left,right; 
        switch (phi)
    {  
        case 1:  
            left = 5;  
            right = 1;  
            break;  
        case 2:  
            left = 1;  
            right = 2;  
            break;  
        case 3:  
            left = 2;  
            right = 3;  
            break;  
        case 4:  
            left = 3;  
            right = 4;  
            break;  
        case 5:  
            left = 4;  
            right = 5;  
            break; 
    }  
    while(1)
    {  
        printf("Philosopher %d is thiking !\n",phi);
        sleep(1); // thinking

        if(phi%2 != 0)//Odd Number
        {
            pthread_mutex_lock(&chopstick[left]); // Ruquest left chopstick
            time_t timep11;
            time (&timep11);
            printf("Philosopher %d takes left chopstick %d at %s",phi,left,asctime(gmtime(&timep11)));
            if (pthread_mutex_trylock(&chopstick[right]))//return 0 if success
            {    
                    pthread_mutex_unlock(&chopstick[left]); // Release left chopstick 
                printf("Philosopher %d release left chopstick %d\n", phi, left);  
                    continue;  
            }  

            time_t timep1;
            time (&timep1);
            printf("Philosopher %d takes right chopstick %d at %s\n",phi,right,asctime(gmtime(&timep11)));
            printf("!!!!!!!!!!!!!!!!!!!!!Philosopher %d is eating~<>_<>~.\n",phi);  
            sleep(3); // eating
            pthread_mutex_unlock(&chopstick[left]); // Release left chopstick 
            printf("Philosopher %d release left chopstick %d\n", phi, left);  
            pthread_mutex_unlock(&chopstick[right]); //  Release right chopstick 
            printf("Philosopher %d release right chopstick %d\n", phi, right);  
            pthread_exit(0);    
        }
        else{
            pthread_mutex_lock(&chopstick[right]); // Ruquest left chopstick
            time_t timep1;
            time (&timep1);
            printf("Philosopher %d takes right chopstick %d at %s",phi,right,asctime(gmtime(&timep1)));

            if (pthread_mutex_trylock(&chopstick[left]))//return 0 if success
            {    
                    pthread_mutex_unlock(&chopstick[right]); // Release left chopstick 
                printf("Philosopher %d release right chopstick %d\n", phi, right);  
                    continue;  
            }  
            time_t timep11;
            time (&timep11);
            printf("Philosopher %d takes left chopstick %d at %s\n",phi,left,asctime(gmtime(&timep11)));
            printf("!!!!!!!!!!!!!!!!!!!!!Philosopher %d is eating~<>_<>~.\n",phi);  
            sleep(3); // eating
            pthread_mutex_unlock(&chopstick[right]); // Release left chopstick 
            printf("Philosopher %d release right chopstick %d\n", phi, right);  
            pthread_mutex_unlock(&chopstick[left]); //  Release right chopstick 
            printf("Philosopher %d release left chopstick %d\n", phi, left);  
            pthread_exit(0);    
        }


        }  
}  

int main()
{  
    int choose;
    printf("Enter 1 for solve1,2 for solve2:\n");
    scanf("%d",&choose);
    pthread_t Philos[Phi_Number];
        int ret[Phi_Number];
            int i,j,k,m;  
        for (i = 0; i < Phi_Number; i++){
            pthread_mutex_init(&chopstick[i],NULL); 
        } 
        int a[5] = {1,2,3,4,5};
    if(choose == 1)
    {

        ret[0] = pthread_create(&Philos[0],NULL,&solve1, &a[0]); 
        ret[1] = pthread_create(&Philos[1],NULL,&solve1, &a[1]); 
        ret[2] = pthread_create(&Philos[2],NULL,&solve1, &a[2]); 
        ret[3] = pthread_create(&Philos[3],NULL,&solve1, &a[3]); 
        ret[4] = pthread_create(&Philos[4],NULL,&solve1, &a[4]); 
        //sleep(1); //指執行緒被呼叫時,佔著CPU不工作,其他執行緒無法進入
    }
    if(choose == 2)
    {
        ret[0] = pthread_create(&Philos[0],NULL,&solve2, &a[0]); 
        ret[1] = pthread_create(&Philos[1],NULL,&solve2, &a[1]); 
        ret[2] = pthread_create(&Philos[2],NULL,&solve2, &a[2]); 
        ret[3] = pthread_create(&Philos[3],NULL,&solve2, &a[3]); 
        ret[4] = pthread_create(&Philos[4],NULL,&solve2, &a[4]); 
        //sleep(1); //指執行緒被呼叫時,佔著CPU不工作,其他執行緒無法進入
    }
    pthread_join(Philos[0],NULL);  
    pthread_join(Philos[1],NULL);
    pthread_join(Philos[2],NULL);
    pthread_join(Philos[3],NULL);
    pthread_join(Philos[4],NULL);

        return 0;  
}

程式碼不足:裡面有許多重複使用的程式碼,沒有實現較好的程式碼複用

主要程式碼提要:

int pthread_mutex_lock(pthread_mutex_t *mutex)
//功能:對訊號量執行P操作
int pthread_mutex_unlock(pthread_mutex_t *mutex)
//功能:對訊號量執行V操作

執行結果截圖:
這裡寫圖片描述

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

相關文章