Я пытаюсь решить Столовая философская проблема используя C ++.
Код скомпилирован с g++ -lpthread
,
Все решение включено философы GitHub. Репозиторий содержит два файла cpp: main.cpp и philopher.cpp. «Main.cpp» создает переменную мьютекса, семафор, 5 условных переменных, 5 вилок и запускает философов. Семафор используется только для синхронизации старта философов. Другие параметры передаются философам для решения проблемы. «Philosopher.cpp» содержит решение для данной проблемы, но после нескольких шагов возникает тупик.
Тупик возникает, когда философ 0 ест, а философ 1 (рядом с ним) хочет взять вилки. Затем философ 1 взял мьютекс и не вернет его, пока философ 0 не опустит свои вилки. Философ 0 не может опустить свои вилки из-за взятия мьютекса, поэтому мы зашли в тупик. Проблема в Метод Philosopher :: take_fork, вызов pthread_cond_wait (a, b) не освобождает мьютекс b. Не можете понять, почему?
// Taking fork. If eather lef or right fork is taken, wait.
void Philosopher::take_fork(){
pthread_mutex_lock(&mon);
std::cout << "Philosopher " << id << " is waiting on forks" << std::endl;
while(!fork[id] || !fork[(id + 1)%N])
pthread_cond_wait(cond + id, &mon);
fork[id] = fork[(id + 1)%N] = false;
std::cout << "Philosopher " << id << " is eating" << std::endl;
pthread_mutex_unlock(&mon);
}
Пожалуйста, ссылку на этот код что касается прочего.
Ваш звонок в pthread_cond_wait()
Это нормально, поэтому проблема должна быть в другом месте. У меня есть три ошибки, которые я вижу:
Во-первых, в main()
вы только инициализируете первый условная переменная в массиве. Вам нужно инициализировать все N
переменные условия:
for(int i = 0; i < N; i++) {
fork[i] = true;
pthread_cond_init(&cond[i], NULL);
}
pthread_mutex_init(&mon, NULL);
Во-вторых, в put_fork()
у вас неверный расчет для одной из переменных условия, чтобы сигнализировать:
pthread_cond_signal(cond + (id-1)%N); /* incorrect */
когда id
равен нулю, (id - 1) % N
равно -1, так что это будет пытаться сигнализировать cond - 1
, который не указывает на переменную условия (возможно, этот указатель фактически повреждает ваш мьютекс, так как он может быть помещен непосредственно перед cond
в стеке). Расчет, который вы на самом деле хотите:
pthread_cond_signal(cond + (id + N - 1) % N);
Третий баг не является причиной вашего тупика, но вы не должны звонить srand(time(NULL))
каждый раз, когда вы звоните rand()
— просто позвоните один раз, в начале main()
,
Других решений пока нет …