## Задача обедающих философов
Пять философов сидят за круглым столом, и у каждого из них есть тарелка спагетти. Эти спагетти настолько скользкие, что есть их можно только двумя вилками. Между каждыми двумя тарелками лежит одна вилка.
Жизнь философа состоит из чередующихся периодов приема пищи и размышлений. (Это положение из разряда абстракций даже в отношении философов, но вся их остальная деятельность к задаче не относится.) Когда философ становится голоден, он старается поочередно в любом порядке завладеть правой и левой вилками. Если ему удастся взять две вилки, он на некоторое время приступает к еде, затем кладет обе вилки на стол и продолжает размышления. Основной вопрос состоит в следующем: можно ли написать программу для каждого философа, который действует предполагаемым образом и никогда при этом не попадает в состояние зависания?
```
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define PHILOSOPERS_NUM 5
//philosophers are THINKING, then become HUNGRY so they start EATING
#define THINKING 0
#define HUNGRY 1
#define EATING 2
#define LEFT_PHILOSOPHER (philosopher_number + 4) % PHILOSOPERS_NUM
#define RIGHT_PHILOSOPHER (philosopher_number + 1) % PHILOSOPERS_NUM
pthread_mutex_t mutex;
pthread_cond_t cond_var[PHILOSOPERS_NUM];
pthread_t threadID[PHILOSOPERS_NUM];
//declare the functions
void *philospher(void *num);
void pickup_forks(int);
void return_forks(int);
void philosopher_can_eat(int);
int state[PHILOSOPERS_NUM];
int philosophers[PHILOSOPERS_NUM] = {0, 1, 2, 3, 4};
void *philospher(void *num)
{
while (1)
{
int x = rand() % 3;
int *i = num;
sleep(x + 1);
printf("%d seconds waited...\n", x + 1);
pickup_forks(*i);
return_forks(*i);
}
}
void pickup_forks(int philosopher_number)
{
//lock first
pthread_mutex_lock(&mutex);
//make philosopher HUNGRY
state[philosopher_number] = HUNGRY;
printf("Philosopher %d is Hungry now \n", philosopher_number + 1);
//get what the philosopher is doing
philosopher_can_eat(philosopher_number);
//wait if he is EATING
if (state[philosopher_number] != EATING)
{
pthread_cond_wait(&cond_var[philosopher_number], &mutex);
}
//else, unlock and sleep for 5 seconds
pthread_mutex_unlock(&mutex);
}
void return_forks(int philosopher_number)
{
//lock first
pthread_mutex_lock(&mutex);
//make philosopher THINKING
state[philosopher_number] = THINKING;
printf("Philosopher %d is PuttingForks %d & %d down.He is Thinking now \n", philosopher_number + 1, LEFT_PHILOSOPHER + 1, philosopher_number + 1);
philosopher_can_eat(LEFT_PHILOSOPHER);
philosopher_can_eat(RIGHT_PHILOSOPHER);
pthread_mutex_unlock(&mutex);
}
void philosopher_can_eat(int philosopher_number)
{
//check the state of the philosophers
//if a philosopher is HUNGRY and his LEFT_PHILOSOPHER and RIGHT_PHILOSOPHER are not EATING then he can eat
if (state[philosopher_number] == HUNGRY && state[LEFT_PHILOSOPHER] != EATING && state[RIGHT_PHILOSOPHER] != EATING)
{
state[philosopher_number] = EATING;
printf("Philosopher %d is PickingUpFork %d & %d.He is Eating now \n", philosopher_number + 1, LEFT_PHILOSOPHER + 1, philosopher_number + 1);
pthread_cond_signal(&cond_var[philosopher_number]);
}
}
int main()
{
int i;
time_t t;
srand((unsigned)time(&t));
pthread_t threadID[PHILOSOPERS_NUM];
//set them all to THINKING initially
for (i = 0; i < PHILOSOPERS_NUM; i++)
{
state[i] = THINKING;
pthread_cond_init(&cond_var[i], NULL);
}
pthread_mutex_init(&mutex, NULL);
for (i = 0; i < PHILOSOPERS_NUM; i++)
{
//create a pthread
pthread_create(&threadID[i], NULL, philospher, &philosophers[i]);
printf("Philosopher %d is Thinking now \n", i + 1);
}
for (i = 0; i < PHILOSOPERS_NUM; i++)
{
pthread_join(threadID[i], NULL);
}
pthread_mutex_destroy(&mutex);
}
```
## Задача читателей и писателей
ней моделируется доступ к базе данных. Представим, к примеру, систему бронирования авиабилетов, в которой есть множество соревнующихся процессов, желающих обратиться к ней для чтения и записи. Вполне допустимо наличие нескольких процессов, одновременно считывающих информацию из базы данных, но если один процесс обновляет базу данных (проводит операцию записи), никакой другой процесс не может получить доступ к базе данных даже для чтения информации. Вопрос в том, как создать программу для читателей и писателей?