Click here to Skip to main content
15,936,709 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
The solution to the problem of dining philosophers
The solution to the process synchronization problem is Semaphores, a semaphore is an integer used in solving critical sections.
A critical section is a part of the program that allows you to access shared variables or resources. In a critical section, an atomic operation (independently running process) is required, meaning that only one process can run in that section at a time.
Semaphore has two atomic operations: wait() and signal(). If its input value S is positive, the wait() operation is decremented, used to get the resource on entry. If S is negative or zero, no operation is performed. The parameter value of the signal() operation S is incremented, it is used to release the resource when the critical section is executed on exit.
Can I solve this problem without a deadlock or how can I change this code?
output:Philosopher 1 is thinking 
Philosopher 1 is eating 
Philosopher 3 is thinking 
Philosopher 3 is eating 
Philosopher 2 is thinking 
Philosopher 4 is thinking 
Philosopher 5 is thinking 
Philosopher 1 Finished eating 
Philosopher 3 Finished eating 
Philosopher 4 is eating 
Philosopher 2 is eating 
Philosopher 5 is eating 
Philosopher 4 Finished eating 
Philosopher 2 Finished eating 
Philosopher 5 Finished eating 


What I have tried:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_PHILOSOPHERS 5
#define NUM_CHOPSTICKS 5

void dine(int n);
pthread_t philosopher[NUM_PHILOSOPHERS];
pthread_mutex_t chopstick[NUM_CHOPSTICKS];

int main()
{
  // Define counter var i and status_message
  int i, status_message;
  void *msg;

  // Initialise the semaphore array
  for (i = 1; i <= NUM_CHOPSTICKS; i++)
  {
    status_message = pthread_mutex_init(&chopstick[i], NULL);
    // Check if the mutex is initialised successfully
    if (status_message == -1)
    {
      printf("\n Mutex initialization failed");
      exit(1);
    }
  }

  // Run the philosopher Threads using *dine() function
  for (i = 1; i <= NUM_PHILOSOPHERS; i++)
  {
    status_message = pthread_create(&philosopher[i], NULL, (void *)dine, (int *)i);
    if (status_message != 0)
    {
      printf("\n Thread creation error \n");
      exit(1);
    }
  }

  // Wait for all philosophers threads to complete executing (finish dining) before closing the program
  for (i = 1; i <= NUM_PHILOSOPHERS; i++)
  {
    status_message = pthread_join(philosopher[i], &msg);
    if (status_message != 0)
    {
      printf("\n Thread join failed \n");
      exit(1);
    }
  }

  // Destroy the chopstick Mutex array
  for (i = 1; i <= NUM_CHOPSTICKS; i++)
  {
    status_message = pthread_mutex_destroy(&chopstick[i]);
    if (status_message != 0)
    {
      printf("\n Mutex Destroyed \n");
      exit(1);
    }
  }
  return 0;
}
void dine(int n)
{
  printf("\nPhilosopher % d is thinking ", n);

  // Philosopher picks up the left chopstick (wait)
  pthread_mutex_lock(&chopstick[n]);

  // Philosopher picks up the right chopstick (wait)
  pthread_mutex_lock(&chopstick[(n + 1) % NUM_CHOPSTICKS]);

  // After picking up both the chopstick philosopher starts eating
  printf("\nPhilosopher % d is eating ", n);
  sleep(3);

  // Philosopher places down the left chopstick (signal)
  pthread_mutex_unlock(&chopstick[n]);

  // Philosopher places down the right chopstick (signal)
  pthread_mutex_unlock(&chopstick[(n + 1) % NUM_CHOPSTICKS]);

  // Philosopher finishes eating
  printf("\nPhilosopher % d Finished eating ", n);
} 
Posted
Updated 30-Dec-22 14:14pm
v2
Comments
OriginalGriff 28-Dec-22 9:01am    
And?
What does it do that you didn't expect, or not do that you did?
What have you tried to do to find out why?
Are there any error messages, and if so, where and when? What did you do to make them happen?

This is not a good question - we cannot work out from that little what you are trying to do.
Remember that we can't see your screen, access your HDD, or read your mind - we only get exactly what you type to work with.
Use the "Improve question" widget to edit your question and provide better information.

According to the console output, Phs 1 and 3 start eating and finish.
That afterwards Ph 4,2 and 5 eat should not work, because the mutex semaphores should prevent two adjacent Phs. The semaphores should all be initialized before the Phs start.

Here are some problems.

Fields start with 0 in C, and not with 1, so it can't work like that:
C
// Initialise the semaphore array
  for (i = 1; i <= NUM_CHOPSTICKS; i++) {...}

// Run the philosopher Threads using *dine() function
  for (i = 1; i <= NUM_PHILOSOPHERS; i++) {...}

Obviously the first elements are not initialized at all and with some certainty something else is overwritten instead.

There may be delays in the output, since on the one hand the line feed is missing and on the other hand the buffer is not written safely.
C++
printf("\nPhilosopher % d is eating ", n);

use instead
C
printf("Philosopher %d is eating\n", n);
fflush(stdout);

And the remark of Karsten with %d would also have to be considered.

The idea to cast an integer as a pointer should actually lead to warnings starting from 64Bit. I don't think this is a good idea.

The solution is a naïve approach that does not prevent the same people from eating all the time, nor does it prevent everyone from starving.
 
Share this answer
 
A problem can be that you create all tasks in running mode, so the first may run and end while the others havent been created. Insert a global mutex to start them all at once.

You better seperate the code more into functions to better see what is going on.

At least you should correct your printing bugs by removing the space between % and d.
C++
void dine(int n)
{
  printf("\nPhilosopher %d is thinking ", n);
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900