What is Philosophers?
Philosophers is a C-based implementation of the classic Dining Philosophers Problem, a fundamental synchronization challenge in concurrent programming. This project demonstrates advanced concepts in multi-threading, mutual exclusion, and deadlock prevention using POSIX threads (pthread) and mutexes.
This project is part of the 42 curriculum and serves as a practical introduction to concurrent programming and resource synchronization challenges.
Why Does It Exist?
The Dining Philosophers Problem is one of the most famous problems in computer science, originally formulated by Edsger Dijkstra in 1965. This implementation exists to:- Teach Concurrency: Provide hands-on experience with multi-threaded programming
- Demonstrate Synchronization: Show practical solutions to resource sharing and deadlock prevention
- Explore Race Conditions: Illustrate how to safely manage shared state between threads
- Practice C Programming: Apply low-level systems programming skills in a challenging context
What Problem Does It Solve?
The project tackles several critical challenges in concurrent systems:Resource Contention
Multiple philosophers (threads) compete for limited resources (forks/mutexes) without causing deadlock
Starvation Prevention
Ensures no philosopher starves by monitoring meal times and preventing indefinite resource denial
Race Condition Management
Uses mutexes to protect shared state and prevent data races between concurrent threads
Timing Precision
Implements precise time tracking to monitor philosopher states and enforce timing constraints
Key Features
Thread-Based Architecture
The implementation creates one thread per philosopher, plus a monitor thread that oversees the entire simulation:Mutex-Based Synchronization
Each fork is represented by a mutex, and the program uses multiple mutexes to protect shared resources:- Fork mutexes: One per fork (shared between adjacent philosophers)
- Write mutex: Protects console output from race conditions
- Dead mutex: Guards the death flag that stops simulation
- Meal mutex: Protects meal counter updates
Deadlock Prevention
The program prevents deadlock through several mechanisms:- Even philosophers delay start: Creates asymmetry to break circular wait
- Single philosopher special case: Handles edge case where only one fork exists
- Consistent lock ordering: Each philosopher locks right fork then left fork
Real-Time Monitoring
A dedicated monitor thread continuously checks for two termination conditions:- Death condition: Any philosopher hasn’t eaten within
time_to_diemilliseconds - Completion condition: All philosophers have eaten at least
max_mealstimes (if specified)
Precise Time Management
The program tracks microsecond-precision timestamps for:- Simulation start time
- Last meal time for each philosopher
- Action timestamps for logging
Program Arguments
The program accepts 4 or 5 arguments:- number_of_philosophers: Number of philosophers and forks (max 600)
- time_to_die: Time in milliseconds before a philosopher dies from starvation
- time_to_eat: Time in milliseconds a philosopher spends eating
- time_to_sleep: Time in milliseconds a philosopher spends sleeping
- number_of_times_each_philosopher_must_eat: Optional simulation stop condition
All time values are in milliseconds and must be positive integers. The program validates all inputs before starting the simulation.
Project Structure
The codebase is organized into focused modules:main.c- Entry point and program flowphilo.h- Data structures and function declarationsinit_data.c- Initialization of tables, philosophers, and mutexesparse_input.c- Input validation and parsingcreate_threads.c- Thread creation and philosopher routinephilo_actions.c- Philosopher actions (eat, sleep, think)monitor.c- Death checking and simulation monitoringtime_utils.c- Time-related utility functionsutils.c- General utility functions
Next Steps
Problem Description
Learn about the classic dining philosophers problem in detail
Getting Started
Build and run the simulation on your system