Skip to content

yssrexe/Philosopher

Repository files navigation

Philosophers

A multithreaded simulation of the classic Dining Philosophers problem, implemented in C using POSIX threads and mutexes.

📖 Description

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.

🎯 Rules

  • 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

🚀 Usage

Compilation

cd philo
make

Execution

./philo number_of_philosophers time_to_die time_to_eat time_to_sleep [number_of_times_each_philosopher_must_eat]

Parameters

  • number_of_philosophers: The number of philosophers and also the number of forks
  • time_to_die (in milliseconds): If a philosopher doesn't start eating within this time since the beginning of their last meal, they die
  • time_to_eat (in milliseconds): The time it takes for a philosopher to eat
  • time_to_sleep (in milliseconds): The time a philosopher spends sleeping
  • number_of_times_each_philosopher_must_eat (optional): If specified, the simulation stops when all philosophers have eaten at least this many times

Examples

# 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 200

📋 Output Format

The 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
...

🏗️ Project Structure

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

🔧 Implementation Details

Key Features

  • Thread Safety: Uses mutexes to protect shared resources and prevent data races
  • Precise Timing: Custom ft_usleep implementation 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

Synchronization

  • 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

🧪 Testing

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

🧹 Cleanup

# Remove object files
make clean

# Remove object files and executable
make fclean

# Rebuild from scratch
make re

📝 Notes

  • 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

👤 Author

yael-yas

📅 Project Timeline

  • Created: March 25, 2025
  • Last Updated: April 4, 2025

This project is part of the 42 School curriculum

About

A multithreaded C implementation of the Dining Philosophers problem using POSIX threads and mutexes to prevent deadlock and starvation

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors