linux c学习之哲学家就餐问题

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/tangnianji_csdn/article/details/75134700

哲学家就餐问题

         哲学家就餐问题。这是由计算机科学家Dijkstra提出的经典死锁场景。
         原版的故事里有五个哲学家,这些哲学家们只做两件事--思考和吃饭,他们思考的时候不需要任何共享资源,但是吃饭的时候就必须使用餐具,而餐桌上的餐具是有限的,原版的故事里,餐具是叉子,吃饭的时候要用两把叉子把面条从碗里捞出来。很显然把叉子换成筷子会更合理,所以:一个哲学家需要两根筷子才能吃饭。
         现在引入问题的关键:这些哲学家很穷,只买得起五根筷子。他们坐成一圈,两个人的中间放一根筷子。哲学家吃饭的时候必须同时得到左手边和右手边的筷子。如果他身边的任何一位正在使用筷子,那他只有等着。

         哲学家在吃面条时一次只能拿一根筷子,拿完一根筷子后,如果另外一根筷子还没有被拿走,则哲学家拿走一根筷子。最后吃面条,放下餐具,思考。这个问题中,首先假设哲学家吃饭占用0~9秒,思考占用0~9秒。

          现在分析一下哲学家就餐问题到底什么时候会出现死锁,很简单!当所有哲学家都是同一边的拿到筷子(比如:左边),则每个哲学家会一直等待旁边的哲学家放下手中的筷子,如此循环则出现了死锁。解决的思路则是,哲学家两边都有筷子的时候才拿起筷子,否则继续思考。这样保证了不会出现有哲学家只拿到一根筷子,然后一直在等待的问题。下面则编写代码解决这个问题。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>

#define NUM    5

struct phi
{
    int left;
    int right;
};

int chopsticks[NUM] = {1, 2, 3, 4, 5};
struct phi philosopthers[NUM];
pthread_mutex_t chopstick1, chopstick2, chopstick3, chopstick4, chopstick5;

void var_init ( void )
{
    int i = 0;
    
    for ( i = 0; i < NUM; i++ )
    {
        philosopthers[i].left = 0;
        philosopthers[i].right = 0;
    }
}

void *philosopther1 ( void *var )
{    
    while ( 1 )
    {
        sleep (rand () % 10 );
        pthread_mutex_lock ( &chopstick5 );
        if ( chopsticks[4] > 0 )
        {
            printf ( "pthilosoptherA fetches chopstick 5\n" );
            chopsticks[4] = 0;
            philosopthers[0].left = 1;
        }
        pthread_mutex_unlock ( &chopstick5 );
        pthread_mutex_lock ( &chopstick1 );    
        if ( chopsticks[0] > 0 && chopsticks[4] == 0)    
        {
            printf ( "philosoptherA fetches chopstick 1\n" );
            chopsticks[0] = 0;
            philosopthers[0].right = 1;
        }
        pthread_mutex_unlock ( &chopstick1 );    
        if ( philosopthers[0].left == 1 && philosopthers[0].right == 1 )    
        {
            sleep ( rand () % 10 );
            chopsticks[4] = 1;
            chopsticks[0] = 1;
            philosopthers[0].left = 0;
            philosopthers[0].right = 0;
        }
    }
    
    return NULL;
}

void *philosopther2 ( void *var )
{
        while ( 1 )
        {
                 sleep (rand () % 10 );
                 pthread_mutex_lock ( &chopstick1 );
                 if ( chopsticks[0] > 0 )
                 {
                         printf ( "pthilosoptherB fetches chopstick 1\n" );
                         chopsticks[0] = 0;
                         philosopthers[1].left = 1;
                 }
                 pthread_mutex_unlock ( &chopstick1 );
                 pthread_mutex_lock ( &chopstick2 );
                 if ( chopsticks[1] > 0 && chopsticks[0] == 0)
                 {
                         printf ( "philosoptherB fetches chopstick 2\n" );
                         chopsticks[1] = 0;
                         philosopthers[1].right = 1;
                 }
                 pthread_mutex_unlock ( &chopstick2 );
                 if ( philosopthers[1].left == 1 && philosopthers[1].right == 1 )
                 {
                         sleep ( rand () % 10 );
                         chopsticks[0] = 1;
                         chopsticks[1] = 1;
                         philosopthers[1].left = 0;
                         philosopthers[1].right = 0;
                 }
         }
 
         return NULL;
 }

void *philosopther3 ( void *var )
{
        while ( 1 )
        {
                 sleep (rand () % 10 );
                 pthread_mutex_lock ( &chopstick2 );
                 if ( chopsticks[1] > 0 )
                 {
                         printf ( "pthilosoptherC fetches chopstick 2\n" );
                         chopsticks[1] = 0;
                         philosopthers[2].left = 1;
                 }
                 pthread_mutex_unlock ( &chopstick2 );
                 pthread_mutex_lock ( &chopstick3 );
                 if ( chopsticks[2] > 0 && chopsticks[1] == 0)
                 {
                         printf ( "philosoptherC fetches chopstick 3\n" );
                         chopsticks[2] = 0;
                         philosopthers[2].right = 1;
                 }
                 pthread_mutex_unlock ( &chopstick3 );
                 if ( philosopthers[2].left == 1 && philosopthers[2].right == 1 )
                 {
                         sleep ( rand () % 10 );
                         chopsticks[1] = 1;
                         chopsticks[2] = 1;
                         philosopthers[2].left = 0;
                         philosopthers[2].right = 0;
                 }
         }
 
         return NULL;
 }

void *philosopther4 ( void *var )
{    
    while ( 1 )
    {
        sleep (rand () % 10 );
        pthread_mutex_lock ( &chopstick3 );
        if ( chopsticks[2] > 0 )
        {
            printf ( "pthilosoptherD fetches chopstick 3\n" );
            chopsticks[2] = 0;
            philosopthers[3].left = 1;
        }
        pthread_mutex_unlock ( &chopstick3 );
        pthread_mutex_lock ( &chopstick4 );    
        if ( chopsticks[3] > 0 && chopsticks[2] == 0)    
        {
            printf ( "philosoptherD fetches chopstick 4\n" );
            chopsticks[3] = 0;
            philosopthers[3].right = 1;
        }
        pthread_mutex_unlock ( &chopstick4 );    
        if ( philosopthers[3].left == 1 && philosopthers[3].right == 1 )    
        {
            sleep ( rand () % 10 );
            chopsticks[2] = 1;
            chopsticks[3] = 1;
            philosopthers[3].left = 0;
            philosopthers[3].right = 0;
        }
    }
    
    return NULL;
}

void *philosopther5 ( void *var )
{    
    while ( 1 )
    {
        sleep (rand () % 10 );
        pthread_mutex_lock ( &chopstick4 );
        if ( chopsticks[3] > 0 )
        {
            printf ( "pthilosoptherE fetches chopstick 4\n" );
            chopsticks[3] = 0;
            philosopthers[4].left = 1;
        }
        pthread_mutex_unlock ( &chopstick4 );
        pthread_mutex_lock ( &chopstick5 );    
        if ( chopsticks[4] > 0 && chopsticks[3] == 0)    
        {
            printf ( "philosoptherE fetches chopstick 5\n" );
            chopsticks[4] = 0;
            philosopthers[4].right = 1;
        }
        pthread_mutex_unlock ( &chopstick5 );    
        if ( philosopthers[4].left == 1 && philosopthers[4].right == 1 )    
        {
            sleep ( rand () % 10 );
            chopsticks[3] = 1;
            chopsticks[4] = 1;
            philosopthers[4].left = 0;
            philosopthers[4].right = 0;
        }
    }
    
    return NULL;
}

int main ( int argc, char *argv[] )
{
    pthread_t tidA, tidB, tidC, tidD, tidE;
    
    srand ( time ( NULL ) );
    var_init ();
    pthread_mutex_init ( &chopstick1, NULL );
    pthread_mutex_init ( &chopstick2, NULL );
    pthread_mutex_init ( &chopstick3, NULL );
    pthread_mutex_init ( &chopstick4, NULL );
    pthread_mutex_init ( &chopstick5, NULL );
    pthread_create ( &tidA, NULL, philosopther1, NULL );
    pthread_create ( &tidB, NULL, philosopther2, NULL );
    pthread_create ( &tidC, NULL, philosopther3, NULL );
    pthread_create ( &tidD, NULL, philosopther4, NULL );
    pthread_create ( &tidE, NULL, philosopther5, NULL );
    
    pthread_join ( tidA, NULL );
    pthread_join ( tidB, NULL );
    pthread_join ( tidC, NULL );
    pthread_join ( tidD, NULL );
    pthread_join ( tidE, NULL );
        
    return 0;
}

展开阅读全文

没有更多推荐了,返回首页