This project has been created as part of the 42 curriculum by moabed
A simplified implementation of the classic Dining Philosophers Problem using Unix threads in C.
This project explores π§΅ threads, π synchronization, β±οΈ timing, and π§ memory concepts in a practical and visual way.
- π Processes vs Threads
- π€Ή The CPU & Scheduling
- 𧬠Creating Life with
fork() - π£οΈ Inter-Process Communication (IPC)
- π Synchronization & Semaphores
- π§΅ Unix Threads in C (
pthread) β οΈ Race Conditions- π Mutexes
- β±οΈ Time Handling with
gettimeofday()
- What is it? A standalone program running in memory.
- Isolation: Fully independent. If one house burns down, the neighbor is safe.
- Cost: Expensive to build (heavy system resources).
- Privacy: Has its own private kitchen (Memory) and keys (Permissions).
- What is it? A worker living inside the Process.
- Sharing: Share the kitchen (Heap), living room (Global Variables), and bathroom (Files).
- Risk: If one roommate causes a segfault π₯, the whole house crashes.
- The Illusion: It looks like 10 apps are running at once.
- Reality: The CPU is juggling.
- Runs App A for 0.001 seconds
- Switches to App B
- Then back to App A
The moment the CPU pauses one task to run another.
The operating system's "Boss" that decides:
- Who runs next
- For how long
- With what priority
| Concept | Analogy |
|---|---|
| Concurrency | One juggler handling 3 balls (time-slicing) |
| Parallelism | Three jugglers, each with 1 ball (multi-core CPU) |
When using fork(), you clone the current process.
- π¨ Parent β The original
- πΆ Child β The duplicate
Both continue execution from the same point.
0β You're in the ChildPIDβ You're in the Parent-1β Error occurred
If a child process finishes but the parent does not call wait() or waitpid():
- The child becomes a Zombie process
- It is dead, but still occupies system resources
Processes are isolated, so they need special tools to communicate.
| Method | Analogy | Speed | Safety |
|---|---|---|---|
| Pipe | Pneumatic tube π¦ | Slower | High |
| Shared Memory | Shared whiteboard π | Very Fast | Risky (Race conditions) |
Two threads try to modify the same variable at the same time.
Result?
- Corrupted data
- Unexpected behavior
- Crashes
Think of it as a single-bathroom key.
- Is key available?
- Yes β Take it and enter.
- No β Wait outside.
- Leave bathroom.
- Put key back.
- Next waiting thread enters.
An atomic operation:
- Happens in one indivisible step
- Cannot be interrupted
- Guarantees consistency
To use threads in C:
#include <pthread.h>Used to define a thread:
pthread_t thread;Creates a new thread.
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);- Pointer to thread
- Thread attributes
- Function the thread will execute
- Argument passed to the function
0β Success- Non-zero β Error code
Waits for a thread to finish.
int pthread_join(pthread_t thread, void **retval);- Thread to wait for
- Pointer to return value
Do NOT create and join the same thread inside the same loop iteration.
β That makes your program run sequentially
β
Create all threads first, then join them
A data race occurs when:
- Two or more threads
- Access shared memory
- At the same time
- And at least one modifies it
Result β Undefined behavior.
A mutex (Mutual Exclusion) prevents race conditions.
pthread_mutex_tβ Declare mutexpthread_mutex_init()β Initializepthread_mutex_lock()β Lockpthread_mutex_unlock()β Unlockpthread_mutex_destroy()β Destroy
pthread_mutex_t lock;
pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);
/* Critical Section */
pthread_mutex_unlock(&lock);
pthread_mutex_destroy(&lock);Include:
#include <sys/time.h>struct timeval current_time;
gettimeofday(¤t_time, NULL);
printf("Current time (microseconds): %ld\n", current_time.tv_usec);tv_secβ Secondstv_usecβ Microseconds
Useful for:
- Measuring philosopher eating time π
- Death timing β³
- Logging events
This project demonstrates:
- π§ Thread lifecycle management
- π Proper synchronization
- β±οΈ Time-based simulation
- π« Avoiding deadlocks
- π¦ Preventing race conditions
It is a simplified ("Lite") version of the Dining Philosophers problem designed to strengthen understanding of:
- Concurrency
- Parallelism
- System-level programming
- Resource sharing
- CPU scheduling
Understanding threads and synchronization is fundamental for:
- Operating Systems
- High-performance servers
- Real-time systems
- Game engines
- Embedded systems
1- compilation: run "make" in the philo directory to execute the code
2- execution: to run the program just type ./philo < number_of_philosophers > < time_to_die (in milliseconds) > < time_to_eat (in milliseconds) > < time_to_sleep (in milliseconds) >
< number_of_times_each_philosopher_must_eat (optional argument) > If all philosophers have eaten at least number_of_times_each_philosopher_must_eat times, the simulation stops. If not specified, the simulation stops when a philosopher dies.
-
Unix Threads in C : https://youtube.com/playlist?list=PLfqABt5AS4FmuQf70psXrsMLEDQXNkLq2&si=gpauzSCOB-1u4DzD
-
The Dining Philosophers Problem : https://youtu.be/FYUi-u7UWgw?si=0zYeElF9Z37hYNKL
-
42-Philosophers : https://youtube.com/playlist?list=PLGU1kcPKHMKi41Py2kqxdvqYE3M9VhCHe&si=fp7ERBaJCK2Ym5zy
I used AI in a logical way to help me in error handling , clarifying some concepts.