Обобщения
Для реализации
, пока сотрудник типа X находится в коридоре, один или несколько дополнительныхсотрудники такого типа прибывают и хотят воспользоваться уже полученным разрешением для первого
, сначала вам нужно сделать так, чтобы эта ситуация даже возникла.В настоящее время у вас никогда не бывает более одного emp1
или emp2
потока (объединенного) в любой момент времени, потому что вы присоединяетесь к каждому из них перед началом другого.Я думаю, что для этой симуляции вы хотите реализовать случайную задержку между сотрудниками в дополнение к случайному типу сотрудников, запустить все потоки сотрудников с этими задержками между ними, а затем присоединить их все только после того, как они все были запущены.
Кроме того, вам нужно установить какое-то время для прохождения коридора, которое, по крайней мере, иногда дольше, чем задержка между сотрудниками, иначе вы все равно вряд ли получите одного сотрудника, прибывающего, пока другой находится в коридоре.
После этого вам нужно что-то, что моделирует разрешение на прохождение, или, возможно, более эффективно, моделирует тех, кто в данный момент находится в коридоре.Более того, вам нужно сделать это таким образом, чтобы потоки могли блокировать до тех пор, пока, по крайней мере, не будет возможности их продолжить.
Хотя семафоры могут отлично использоваться для некоторых проблем синхронизации потоковситуация, требующая, чтобы потоки сменялись или приобретали владение некоторой ограниченной вещью, обычно требует разделяемой переменной, представляющей принадлежащую вещь / ход, мьютекс, защищающий доступ к этой переменной, и условную переменную, помогающую потокам в ожидании их возможности продолжить.
Подход к реализации
В основном необходимо отслеживать две вещи:
Какой тип сотрудника в настоящее время владеет коридором (тип 1, тип 2, или сопровождающий )
enum { ATTENDANT, TYPE1, TYPE2 } corridor_owner;
и
Сколько сотрудниковв настоящее время находятся в коридоре.
int corridor_occupancy;
Кроме того, все потоки должны полагаться на один и тот же мьютекс для защиты доступа к этим данным
pthread_mutex_t corridor_mutex = PTHREAD_MUTEX_INITIALIZER;
и им также понадобится общее резюме
pthread_cond_t corridor_cv = PTHREAD_COND_INITIALIZER;
Имея это, вот достаточно хороший способ решения проблемы:
Когда работник(нить) типа 1 или 2 хочет войти в коридор , они должны выполнить следующую процедуру:
- Получить мьютекс.
- Проверить, принадлежит ли коридор в настоящее времядругой тип сотрудника, и он уже занят:
- , если это так, дождитесь резюме и, вернувшись из ожидания, перезапустите шаг (2);
- , если нет, запросите коридор для еговведите тип сотрудника (возможно, с избыточностью) и увеличьте количество занятых в коридоре.
- Отключите мьютекс
Обратите внимание, что это позволяет нескольким сотрудникам одного типа проходить черезкоридор в то же время.
Когда оператор хочет войти в коридор , он выполняет другую процедуру:
- Получение мьютекса.
- Проверьте, является ли коридорпринадлежит другому типу сотрудника и уже занята:
- , если это так, сначала отпустите мьютекс, затем поспите одну секунду, затем вернитесь к шагу (1);
- , если нет,запросить коридор для его типа сотрудника, увеличить счетчик занятости коридора, а затем освободить мьютекс.
Когда сотрудник любого типа покидает коридор , он должен
- получить мьютекс
- уменьшить счетчик занятости
- , если счетчик занятости равен нулю, то разбудить все потоки, ожидающие на CV
- освободи мьютекс
Кроме того, когда поток обслуживающего персонала покидает коридор, он должен поспать некоторое время, а затем вернуться назад, чтобы попытаться снова выполнить очистку - поскольку вы в настоящее время реализовали это, он очищается только один раз. Вам также нужно либо реализовать какой-то сигнал для остановки потока обслуживающего персонала, либо сделать его потоком демона (а не пытаться присоединиться к нему).