
Philosophers
Multi-threading and Synchronization
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
Threading Foundation
Set up basic threading structure with pthread library and implemented philosopher lifecycle management.
Synchronization Implementation
Implemented mutex locks for fork access and developed synchronization mechanisms to prevent race conditions.
Deadlock Prevention
Developed deadlock prevention strategies and implemented monitoring system for philosopher state tracking.
Challenges & Solutions
Deadlock Prevention
Preventing deadlock situations where philosophers wait indefinitely for resources in circular dependency.
Implemented resource ordering and timeout mechanisms to break potential deadlock cycles with strategic mutex acquisition.
Race Condition Handling
Ensuring thread-safe access to shared data structures and preventing data corruption in concurrent environment.
Used mutex locks strategically and implemented atomic operations for critical sections with proper synchronization.
Timing Precision
Managing precise timing for eating, sleeping, and death detection in multi-threaded environment.
Implemented high-resolution timing system with proper thread synchronization for accurate state monitoring.
// 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);
}