Philosophers
Threads, mutexes and data races
- Period
- Mar 2025
- Context
- 42 curriculum
- Team
- solo
- Grade
- 100/100 · outstanding ×1
- C
- Low-level
- Algorithms
- Imperative programming
The dining philosophers: philosophers around a table, one fork between each of them, and eating takes two. Each philosopher is a thread, each fork a mutex, and nobody must starve.
The rules
The program takes the number of philosophers, the time to die, the time to eat, the time to sleep, and optionally a number of meals. A philosopher who has not eaten for too long dies, and the simulation must stop at once, reporting it to the millisecond.
My solution
Each fork is a “mutex + value” pair. A thinking philosopher locks both forks, checks that they are free, marks them as taken, then releases the locks: they never hold a mutex while eating, which avoids deadlocks.
Each thread follows a small state machine (think, take forks, eat, sleep) and checks on every iteration whether it has run out of time or a neighbour has died. The meal counter, the “alive” flag and the output each have their own mutex: no shared data is read without a lock.
A bit of fun
The philosophers have names, numbered in Roman numerals, and the output exists in French and English, chosen at compile time.
What I took away
- A data race is not always visible: you prevent it, one lock at a time.
- Hold a mutex for as short a time as possible.
- A thread’s “real” timing depends on the scheduler, not only on the code.