Thread: The Diening Philosophers with POSIX Threads

  1. #1
    Registered User
    Join Date
    Nov 2011
    Posts
    45

    The Diening Philosophers with POSIX Threads

    Hello,

    I'm givin' the Dining Phiolsophers a try to solve it with Mutexs but it's not going to well.

    The Mutex initalisation works, the threads start, the VOID Philosopher must be correct since I translated it from the structure which is in the book I'm reading.

    So it has to be something in the main class are my thaughts.


    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <semaphore.h>
    
    pthread_mutex_t chopsticks[5] = PTHREAD_MUTEX_INITIALIZER;
    void *Philosopher(void *arg);
    
    struct Param {
        int index;
    };
    
    int main(void)
    {
        pthread_t phil0, phil1, phil2, phil3, phil4;
        int i;
        struct Param p[5];
        for(i=0; i<5; i++)
        {
         
            if (pthread_mutex_init(&chopsticks[i],0) != 0)
            {
                printf("Mutex_Init Error\n");
            }
            p[i].index=i;
        }
    
        if(    pthread_create(&phil0, NULL, Philosopher, &p[0]) ||
                pthread_create(&phil1, NULL, Philosopher, &p[1]) ||
                pthread_create(&phil2, NULL, Philosopher, &p[2]) ||
                pthread_create(&phil3, NULL, Philosopher, &p[3]) ||
                pthread_create(&phil4, NULL, Philosopher, &p[4]) )
        {
            printf("Threads Fail\n");
            exit(EXIT_FAILURE);
        }
    
        for(i=0; i<5; i++)
        {
            pthread_mutex_destroy(&chopsticks[i]);
        }
    
        pthread_exit(NULL);
        exit(0);
    }
    
    void *Philosopher(void *arg)
    {
        struct Param *p = (struct Param*)arg;
        int index=p->index;
     
        do{
            pthread_mutex_lock(&chopsticks[index]);
            pthread_mutex_lock(&chopsticks[(index+1)%5]);
    
            // eat
            printf("Philosopher %d is eating \n", index);
             
            pthread_mutex_unlock(&chopsticks[index]);
            pthread_mutex_unlock(&chopsticks[(index+1)%5]);
    
            // think
    
            printf("Philosopher %d is thinking \n", index);
    
            sleep(1);
    
        }while(1);
    }
    The output I experience:
    Code:
    Philosopher 0 is eating 
    Philosopher 0 is thinking 
    Philosopher 2 is eating 
    Philosopher 1 is eating 
    Philosopher 1 is thinking 
    Philosopher 4 is eating 
    Philosopher 3 is eating 
    Philosopher 3 is thinking 
    Philosopher 2 is thinking 
    Philosopher 4 is thinking 
    Philosopher 0 is eating 
    Philosopher 0 is thinking 
    Philosopher 1 is eating

    Also please say why my reasoning is wrong, I'm trying to clean constantly.

    Kind regards

  2. #2
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    edit: what is it doing wrong

    edit: your main program will continue executing after your create the threads. it is a thread also so it will get a chance to run. when it runs it will delete the mutexes and exit which will kill the whole program. your main thread needs to suspend itself after creating the threads. maybe wait for user input or whatever method you want to signal termination.
    Last edited by dmh2000; 03-16-2012 at 09:47 AM.

  3. #3
    Registered User
    Join Date
    Nov 2011
    Posts
    45
    Quote Originally Posted by dmh2000 View Post
    edit: what is it doing wrong

    edit: your main program will continue executing after your create the threads. it is a thread also so it will get a chance to run. when it runs it will delete the mutexes and exit which will kill the whole program. your main thread needs to suspend itself after creating the threads. maybe wait for user input or whatever method you want to signal termination.
    Could you kinly explain a little more.

  4. #4
    Registered User
    Join Date
    Nov 2011
    Posts
    45
    Quote Originally Posted by dmh2000 View Post
    edit: what is it doing wrong

    edit: your main program will continue executing after your create the threads. it is a thread also so it will get a chance to run. when it runs it will delete the mutexes and exit which will kill the whole program. your main thread needs to suspend itself after creating the threads. maybe wait for user input or whatever method you want to signal termination.
    How can I suspend the main thread?

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Quote Originally Posted by MaSSaSLaYeR View Post
    How can I suspend the main thread?
    Already answered:
    maybe wait for user input or whatever method you want to signal termination.

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Remove "= PTHREAD_MUTEX_INITIALIZER" on line 7.

    Replace all instances of "5" with "NUM_PHILOSOPHERS".

    Line 16: Use "pthread_t phils[NUM_PHILOSOPHERS];" instead.

    Line 38: This is where you should wait for your threads to exit via pthread_join().

    Line 44,45: No need, just return from main().

    gg

  7. #7
    Registered User
    Join Date
    Nov 2011
    Posts
    45
    Quote Originally Posted by Codeplug View Post
    Remove "= PTHREAD_MUTEX_INITIALIZER" on line 7.

    Replace all instances of "5" with "NUM_PHILOSOPHERS".

    Line 16: Use "pthread_t phils[NUM_PHILOSOPHERS];" instead.

    Line 38: This is where you should wait for your threads to exit via pthread_join().

    Line 44,45: No need, just return from main().

    gg
    Will try thanks

  8. #8
    Registered User
    Join Date
    Nov 2011
    Posts
    45
    Quote Originally Posted by Codeplug View Post
    Remove "= PTHREAD_MUTEX_INITIALIZER" on line 7.

    Replace all instances of "5" with "NUM_PHILOSOPHERS".

    Line 16: Use "pthread_t phils[NUM_PHILOSOPHERS];" instead.

    Line 38: This is where you should wait for your threads to exit via pthread_join().

    Line 44,45: No need, just return from main().

    gg
    Quote Originally Posted by Codeplug View Post
    Remove "= PTHREAD_MUTEX_INITIALIZER" on line 7.

    Replace all instances of "5" with "NUM_PHILOSOPHERS".

    Line 16: Use "pthread_t phils[NUM_PHILOSOPHERS];" instead.

    Line 38: This is where you should wait for your threads to exit via pthread_join().

    Line 44,45: No need, just return from main().

    gg
    Edited to & still gettin' same bad results

    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <semaphore.h>
    
    
    #define NUM_PHILO 5
    
    pthread_mutex_t chopsticks[NUM_PHILO];
    void *Philosopher(void *arg);
    
    struct Param {
        int index;
    };
    
    int main(void)
    {
        pthread_t phil[NUM_PHILO];
       //thread_t phil0, phil1, phil2, phil3, phil4;
        int i;
        struct Param p[NUM_PHILO];
        for(i=0; i<NUM_PHILO; i++)
        {
         
            if (pthread_mutex_init(&chopsticks[i],0) != 0)
            {
                printf("Mutex_Init Error\n");
            }
            p[i].index=i;
        }
    
        for(i=0; i<NUM_PHILO; i++)
        {
            if(pthread_create(&phil[i],NULL, Philosopher, &p[i]) )
            {
                printf("Threads Fail\n");
                exit(EXIT_FAILURE);
            }
        }
    
        for(i=0; i<NUM_PHILO; i++)
        {
            if(pthread_join(phil[0], NULL) )
            {
                printf("Threads Fail\n");
                exit(EXIT_FAILURE);
            }
        }
        for(i=0; i<NUM_PHILO; i++)
        {
            pthread_mutex_destroy(&chopsticks[i]);
        }    
    }
    
    void *Philosopher(void *arg)
    {
        struct Param *p = (struct Param*)arg;
        int index=p->index;
     
        do{
            pthread_mutex_lock(&chopsticks[index]);
            pthread_mutex_lock(&chopsticks[(index+1)%5]);
    
            printf("Philosopher %d is eating \n", index);
             
            pthread_mutex_unlock(&chopsticks[index]);
            pthread_mutex_unlock(&chopsticks[(index+1)%5]);
    
           printf("Philosopher %d is thinking \n", index);
    
            sleep(1);
    
        }while(1);
    }

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Line 28: Might as well exit() here too.

    Line 44: Forgot to use 'i'.

    Line 63, 68: Missed a few "5"'s

    You can "return 0" from main() and Philosopher().

    This solution can still deadlock, though it may be unlikely to occur. The easy way to "see" the deadlock is to add a "sleep(2)" between lines 62 and 63.

    gg

  10. #10
    Registered User
    Join Date
    Nov 2011
    Posts
    45
    Quote Originally Posted by Codeplug View Post
    Line 28: Might as well exit() here too.

    Line 44: Forgot to use 'i'.

    Line 63, 68: Missed a few "5"'s

    You can "return 0" from main() and Philosopher().

    This solution can still deadlock, though it may be unlikely to occur. The easy way to "see" the deadlock is to add a "sleep(2)" between lines 62 and 63.

    gg
    If I add sleep between the line 62 and 63 I get no results else I get the following results, which I think are not right;


    Code:
    Philosopher 0 is eating 
    Philosopher 0 is thinking 
    Philosopher 4 is eating 
    Philosopher 4 is thinking 
    Philosopher 2 is eating 
    Philosopher 2 is thinking 
    Philosopher 1 is eating 
    Philosopher 1 is thinking 
    Philosopher 3 is eating 
    Philosopher 3 is thinking 
    Philosopher 4 is eating 
    Philosopher 4 is thinking 
    Philosopher 1 is eating 
    Philosopher 1 is thinking




    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <semaphore.h>
    
    
    #define NUM_PHILO 5
    
    pthread_mutex_t chopsticks[NUM_PHILO];
    void *Philosopher(void *arg);
    
    struct Param {
        int index;
    };
    
    int main(void)
    {
        pthread_t phil[NUM_PHILO];
       //thread_t phil0, phil1, phil2, phil3, phil4;
        int i;
        struct Param p[NUM_PHILO];
        for(i=0; i<NUM_PHILO; i++)
        {
         
            if (pthread_mutex_init(&chopsticks[i],0) != 0)
            {
                printf("Mutex_Init Error\n");
                exit(EXIT_FAILURE);
            }
            p[i].index=i;
        }
    
        for(i=0; i<NUM_PHILO; i++)
        {
            if(pthread_create(&phil[i],NULL, Philosopher, &p[i]) )
            {
                printf("Threads Fail\n");
                exit(EXIT_FAILURE);
            }
        }
    
        for(i=0; i<NUM_PHILO; i++)
        {
            if(pthread_join(phil[i], NULL) )
            {
                printf("Threads Fail\n");
                exit(EXIT_FAILURE);
            }
        }
        for(i=0; i<NUM_PHILO; i++)
        {
            pthread_mutex_destroy(&chopsticks[i]);
        }    
    
        return 0;
    }
    
    void *Philosopher(void *arg)
    {
        struct Param *p = (struct Param*)arg;
        int index=p->index;
     
        do{
            pthread_mutex_lock(&chopsticks[index]);
            //sleep(2);
            pthread_mutex_lock(&chopsticks[(index+1)%NUM_PHILO]);
    
            printf("Philosopher %d is eating \n", index);
             
            pthread_mutex_unlock(&chopsticks[index]);
            pthread_mutex_unlock(&chopsticks[(index+1)%NUM_PHILO]);
    
           printf("Philosopher %d is thinking \n", index);
    
            sleep(1);
    
        }while(1);
    
        return 0;
    }

  11. #11
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    If you sleep (long enough, and 2 seconds is plenty) after the first lock then every thread will get a chance to lock its assigned mutex. Then the next lock will block forever.

    What do you think is wrong with your output? What do you expect?
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  12. #12
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> If I add sleep between the line 62 and 63 I get no results
    That's the deadlock

    >> I get the following results, which I think are not right
    Looks like valid output to me. As you have it now, the only invalid output is if one or more of the philosophers have no output.

    You can randomize how long each philosopher thinks and eats, which should mix up the results and make it more likely to have more than 1 eater at a time.
    Code:
    sleep((rand() % 3) + 1); // sleep between 1 and 3 seconds
    You could also improve the logging in your loop:
    Code:
    while (1)
    {
        thinking = (rand() % 3) + 1
        printf("Philosopher %d is thinking for %d seconds\n", index, thinking);
        fflush(stdout);
        
        sleep(thinking);
        
        printf("Philosopher %d is hungry\n", index);
        fflush(stdout);
        
        <acquire forks/sticks>
        
        eating = (rand() % 3) + 1
        printf("Philosopher %d is eating for %d seconds\n", index, eating);
        fflush(stdout);
        
        sleep(eating);
        
        printf("Philosopher %d is done eating\n", index);
        fflush(stdout);
        
        <put down forks/sticks>
    }
    gg

  13. #13
    Registered User
    Join Date
    Nov 2011
    Posts
    45
    The normal out for Dining Philosopher is:

    Phil 0 thinking
    Phil 1 thinking
    Phil 3 eating
    Phil 4 thinking

    Only one Phil can eat at any given time or am i wrong?

    Dining philosophers problem - Wikipedia, the free encyclopedia

  14. #14
    Registered User
    Join Date
    Nov 2011
    Posts
    45
    Quote Originally Posted by Codeplug View Post
    >> If I add sleep between the line 62 and 63 I get no results
    That's the deadlock

    >> I get the following results, which I think are not right
    Looks like valid output to me. As you have it now, the only invalid output is if one or more of the philosophers have no output.

    You can randomize how long each philosopher thinks and eats, which should mix up the results and make it more likely to have more than 1 eater at a time.
    Code:
    sleep((rand() % 3) + 1); // sleep between 1 and 3 seconds
    You could also improve the logging in your loop:
    Code:
    while (1)
    {
        thinking = (rand() % 3) + 1
        printf("Philosopher %d is thinking for %d seconds\n", index, thinking);
        fflush(stdout);
        
        sleep(thinking);
        
        printf("Philosopher %d is hungry\n", index);
        fflush(stdout);
        
        <acquire forks/sticks>
        
        eating = (rand() % 3) + 1
        printf("Philosopher %d is eating for %d seconds\n", index, eating);
        fflush(stdout);
        
        sleep(eating);
        
        printf("Philosopher %d is done eating\n", index);
        fflush(stdout);
        
        <put down forks/sticks>
    }
    gg
    You cracked it thanks a lot That's what I searched for.

    Thanks a lot of your expertise and kind help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A Qn on Posix threads
    By sangamesh in forum C Programming
    Replies: 3
    Last Post: 06-11-2011, 11:04 AM
  2. Posix Threads
    By tsiknas in forum Linux Programming
    Replies: 2
    Last Post: 11-28-2009, 04:07 AM
  3. POSIX threads
    By Boylett in forum Linux Programming
    Replies: 2
    Last Post: 09-10-2008, 01:33 PM
  4. Using POSIX threads in C on Linux
    By muthus in forum C Programming
    Replies: 1
    Last Post: 01-19-2008, 05:34 PM
  5. POSIX-Threads
    By posixunil in forum Linux Programming
    Replies: 2
    Last Post: 04-17-2007, 06:43 AM