A multithreaded simulation of the classic Dining Philosophers problem, implemented in C using POSIX threads and mutexes.
This project simulates the famous dining philosophers problem where philosophers sit at a round table with a bowl of spaghetti. Each philosopher needs two forks to eat, but there is only one fork between each pair of philosophers. The challenge is to design a solution that prevents deadlock and starvation while allowing the philosophers to eat, sleep, and think.
- One or more philosophers sit at a round table with a large bowl of spaghetti in the center
- There is one fork between each pair of philosophers
- A philosopher must eat, sleep, and think
- To eat, a philosopher needs to pick up both the left and right forks
- A philosopher cannot eat with only one fork
- When a philosopher finishes eating, they put down both forks and start sleeping
- After sleeping, they start thinking
- The simulation stops when a philosopher dies of starvation
cd philo
make./philo number_of_philosophers time_to_die time_to_eat time_to_sleep [number_of_times_each_philosopher_must_eat]number_of_philosophers: The number of philosophers and also the number of forkstime_to_die(in milliseconds): If a philosopher doesn't start eating within this time since the beginning of their last meal, they dietime_to_eat(in milliseconds): The time it takes for a philosopher to eattime_to_sleep(in milliseconds): The time a philosopher spends sleepingnumber_of_times_each_philosopher_must_eat(optional): If specified, the simulation stops when all philosophers have eaten at least this many times
# 5 philosophers, die in 800ms, eat in 200ms, sleep in 200ms
./philo 5 800 200 200
# 5 philosophers with eating limit of 7 times each
./philo 5 800 200 200 7
# 4 philosophers, die in 310ms, eat in 200ms, sleep in 100ms
./philo 4 310 200 100
# Single philosopher (should die)
./philo 1 800 200 200The program outputs the state changes of each philosopher in the following format:
[timestamp_in_ms] [philosopher_id] has taken a fork
[timestamp_in_ms] [philosopher_id] is eating
[timestamp_in_ms] [philosopher_id] is sleeping
[timestamp_in_ms] [philosopher_id] is thinking
[timestamp_in_ms] [philosopher_id] died
Example output:
0 1 has taken a fork
0 1 has taken a fork
0 1 is eating
0 3 has taken a fork
0 3 has taken a fork
0 3 is eating
200 1 is sleeping
200 3 is sleeping
200 2 has taken a fork
...
philo/
├── philo.h # Header file with structures and function prototypes
├── main.c # Entry point of the program
├── parsing.c # Input validation and parsing
├── create_philos.c # Philosopher and thread initialization
├── create_philo2.c # Additional initialization helpers
├── routine.c # Main philosopher routine
├── ft_monitor.c # Death monitoring thread
├── eating.c # Eating behavior implementation
├── Sleethink.c # Sleep and think behavior
├── one_philo.c # Special case for single philosopher
├── ft_printf.c # Thread-safe printing utility
├── ft_usleep.c # Precise sleep implementation
├── help_func.c # Helper functions
└── Makefile # Build configuration
- Thread Safety: Uses mutexes to protect shared resources and prevent data races
- Precise Timing: Custom
ft_usleepimplementation for accurate time delays - Death Detection: Dedicated monitor thread checks for philosopher starvation
- Single Philosopher Handling: Special case implementation for edge scenarios
- Clean Exit: Proper cleanup of threads and mutexes on program termination
- Each fork is represented by a mutex
- Philosophers acquire forks in a specific order to prevent deadlock
- A global mutex protects the printing function to prevent log corruption
- Last meal time is protected by individual mutexes for each philosopher
Test with various configurations:
# No one should die
./philo 5 800 200 200
# No one should die, stops when all eat 7 times
./philo 5 800 200 200 7
# Should not die
./philo 4 410 200 200
# Should die
./philo 4 310 200 100
# Single philosopher should die
./philo 1 800 200 200# Remove object files
make clean
# Remove object files and executable
make fclean
# Rebuild from scratch
make re- The program must not have any data races
- Messages should not be mixed between philosophers
- A philosopher's death should be reported within 10ms of the actual death
- The program should handle edge cases like a single philosopher correctly
yael-yas
- Created: March 25, 2025
- Last Updated: April 4, 2025
This project is part of the 42 School curriculum