Philosophers
42 Abu Dhabi

Philosophers

Multi-threading and Synchronization

3 weeks
Individual Project
CPthreadsMutexesConcurrency

Implementation of the classic dining philosophers problem using threads and mutexes, focusing on concurrent programming and deadlock prevention.

Key Features

Philosopher Simulation

Simulated multiple philosophers eating, thinking, and sleeping with realistic timing and behavior patterns.

Mutex Protection

Implemented mutex locks to prevent race conditions and ensure thread-safe access to shared resources.

Death Detection

Real-time monitoring of philosopher states to detect starvation and prevent deadlock situations.

Synchronization

Coordinated multiple threads with proper synchronization to avoid deadlocks and ensure fair resource access.

Development Journey

Phase 1

Threading Foundation

Set up basic threading structure with pthread library and implemented philosopher lifecycle management.

Phase 2

Synchronization Implementation

Implemented mutex locks for fork access and developed synchronization mechanisms to prevent race conditions.

Phase 3

Deadlock Prevention

Developed deadlock prevention strategies and implemented monitoring system for philosopher state tracking.

Challenges & Solutions

Deadlock Prevention

Problem:

Preventing deadlock situations where philosophers wait indefinitely for resources in circular dependency.

Solution:

Implemented resource ordering and timeout mechanisms to break potential deadlock cycles with strategic mutex acquisition.

Race Condition Handling

Problem:

Ensuring thread-safe access to shared data structures and preventing data corruption in concurrent environment.

Solution:

Used mutex locks strategically and implemented atomic operations for critical sections with proper synchronization.

Timing Precision

Problem:

Managing precise timing for eating, sleeping, and death detection in multi-threaded environment.

Solution:

Implemented high-resolution timing system with proper thread synchronization for accurate state monitoring.

philosophers.c
c
// Philosopher structure definition
typedef struct s_philo
{
    int             id;
    pthread_t       thread;
    long            last_meal;
    int             meals_eaten;
    pthread_mutex_t *left_fork;
    pthread_mutex_t *right_fork;
    t_data          *data;
} t_philo;

// Main philosopher routine
void *philosopher_routine(void *arg)
{
    t_philo *philo = (t_philo *)arg;
    
    while (!is_simulation_over(philo->data))
    {
        think(philo);
        take_forks(philo);
        eat(philo);
        put_down_forks(philo);
        sleep_philo(philo);
    }
    return (NULL);
}

// Fork taking with deadlock prevention
void take_forks(t_philo *philo)
{
    pthread_mutex_t *first_fork;
    pthread_mutex_t *second_fork;
    
    // Prevent deadlock by ordering fork acquisition
    if (philo->left_fork < philo->right_fork)
    {
        first_fork = philo->left_fork;
        second_fork = philo->right_fork;
    }
    else
    {
        first_fork = philo->right_fork;
        second_fork = philo->left_fork;
    }
    
    pthread_mutex_lock(first_fork);
    print_status(philo, "has taken a fork");
    
    pthread_mutex_lock(second_fork);
    print_status(philo, "has taken a fork");
}

// Eating function with timing
void eat(t_philo *philo)
{
    pthread_mutex_lock(&philo->data->meal_mutex);
    philo->last_meal = get_time();
    philo->meals_eaten++;
    pthread_mutex_unlock(&philo->data->meal_mutex);
    
    print_status(philo, "is eating");
    usleep(philo->data->time_to_eat * 1000);
}