We have an assignment to show deadlock with the Dining Philosophers problem. We've coded it all and the code compiles but when running the code, one of the philosophers eventually eats. So doesn't that mean deadlock doesn't actually occur?
#include <pthread.h>
#include <stdio.h>
#define number_philo 5
pthread_mutex_t cutlery[number_philo];
void* philosopher (void* number)
{
int my_num = *((int*)number);
while (1)
{
printf("\n Philosopher %d is thinking.\n",my_num);
pthread_mutex_lock (&cutlery[my_num]);
printf("\nPhilosopher %d has left cutlery. \n",my_num);
sleep(3);
pthread_mutex_lock (&cutlery[(my_num + 1) % number_philo]);
printf("\nPhilosopher %d has right cutlery. \n",my_num);
printf("\n Philosopher %d eating.\n", my_num);
printf("\n Philosopher %d done.\n", my_num);
pthread_mutex_unlock (&cutlery[(my_num + 1) % number_philo]);
pthread_mutex_unlock (&cutlery[my_num]);
printf("\nPhilosopher %d no longer has cutlery.\n", my_num);
}
return NULL;
}
int main ()
{
int i;
pthread_t phils[number_philo];
void* return_val;
for (i = 0; i < number_philo; i++)
pthread_mutex_init (&cutlery[i], NULL);
for (i = 0; i < number_philo; i++)
pthread_create (&phils[i], NULL, philosopher, &i);
for (i = 0; i < number_philo; i++)
pthread_join (phils[i], &return_val);
return 0;
}
And this is the output: output
The problem is here:
pthread_create (&phils[i], NULL, philosopher, &i);
You are passing a pointer to the same variable i
to each thread, and those threads (and the main thread) are all accessing i
in a racy way. You'll get multiple philosophers using the same number and some numbers not used at all.
You need to give each philosopher it's own variable to read, or wait for it to read i
before going around the loop and changing i
. An example of the former:
int phil_num[number_philo];
/* ... */
for (i = 0; i < number_philo; i++)
{
phil_num[i] = i;
pthread_create (&phils[i], NULL, philosopher, &phil_num[i]);
}