【发布时间】:2022-01-20 11:33:08
【问题描述】:
我正在尝试为哲学家就餐问题(有五个哲学家)实施一个简单的解决方案,我的解决方案基于这个逻辑:
sem_t S[philosophers_number]
for each philosopher
{
while(TRUE)
{
if(current philosopher number != last philosopher)
{
thinking()
//i is number of current philosopher
sem_wait(take_chopstick(S[(i+1) % philosophers_number])) // right chopstick
sem_wait(take_chopstick(S[i])) // left chopstick
eat()
sem_post(put_chopstick(S[(i+1) % philosophers_number]))
sem_post(put_chopstick(S[i]))
}
else
{
thinking()
//i is number of current philosopher
sem_wait(take_chopstick(S[i])) // left chopstick
sem_wait(take_chopstick(S[(i+1) % philosophers_number])) // right chopstick
eat()
sem_post(put_chopstick(S[i]))
sem_post(put_chopstick(S[(i+1) % philosophers_number]))
}
}
每个哲学家首先思考不到三秒钟
如果右边的筷子可用,哲学家会拿走它,如果还有左边的筷子可用,哲学家也会拿走筷子,然后开始吃不到三秒钟
然后哲学家会放下筷子,让其他哲学家使用
为了避免循环等待,对于最后一位哲学家,我会先选择左筷子,然后选择右筷子,然后继续进行相同的过程
这是我基于这个逻辑实现的代码:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#define THREADS 5
sem_t chopstick[THREADS];
void thinking(int ph_num)
{
printf("philosopher %d is thinking\n", ph_num);
int t = rand() % 3;
sleep(t);// up to 3 secs thinking
}
void eat(int ph_num)
{
printf("philosopher %d is eating\n", ph_num);
int t = rand() % 3;
sleep(t);// up to 3 secs eating
}
void *philosopher(void * ph_num )
{
int num=(int)ph_num;
while(1)
{
if(num < THREADS - 1)
{
thinking(num);
//pick up right chopstick
sem_wait(&chopstick[(num + 1) % THREADS]);
//to make deadlocks absolutly happen, wait 1 sec then pickup left chopstick
sleep(1);
//pick up left chopstick
sem_wait(&chopstick[num]);
eat(num);
//put down right chopstick
sem_post(&chopstick[(num + 1) % THREADS]);
//put down left chopstick
sem_post(&chopstick[num]);
}
else // last one pick left chopstick first, instead of right one to avoid cyclic wait
{
thinking(num);
//pick up left chopstick
sem_wait(&chopstick[num]);
//to make deadlocks absolutly happen, wait 1 sec then pickup left chopstick
sleep(1);
//pick up right chopstick
sem_wait(&chopstick[(num + 1) % THREADS]);
eat(num);
//put down left chopstick
sem_post(&chopstick[num]);
//put down right chopstick
sem_post(&chopstick[(num + 1) % THREADS]);
}
}
pthread_exit((void *)num);
}
int main ()
{
for(int i = 0; i < THREADS; i++)
{
sem_init(&chopstick[i],0,1);
}
pthread_t threads[THREADS];
for(int i = 0; i < THREADS; i++)
pthread_create(&threads[i], NULL, philosopher, (void *)i);
for(int i = 0; i < THREADS; i++)
pthread_join(threads[i],NULL);
return 0;
}
但是在调试这段代码时发生了一个问题,其中chopstick[i] 在sem_wait(&chopstick[num]) 之前是0,而不是阻塞当前线程,直到有筷子可用sem_wait() 继续进行,所以哲学家开始在没有实际筷子的情况下吃饭.
谁能帮我找出问题出在哪里?
【问题讨论】:
-
如何查看信号量的值?我不建议您使用信号量的值进行调试,因为线程可以在您检查该值之后等待/发布,因此尽管结构为真,但该值可能是错误的。附带说明一下,Posix 信号量与此问题不兼容,因为它们不能让您同时对至少两个信号量进行操作。
-
@tango-1 谢谢,但实际上我必须使用 posix 信号量来完成这项任务,并且我正在使用
sem_getvalue()获取信号量的值,但我不确定这是否是正确的方法。跨度>
标签: c multithreading operating-system semaphore dining-philosopher