gpt4 book ai didi

Solve Dining Philosophers Problem Using pthreads, mutex locks, and condition variables(使用p线程、互斥锁和条件变量解决餐饮哲学家问题)

转载 作者:bug小助手 更新时间:2023-10-28 13:27:15 27 4
gpt4 key购买 nike



I'm trying to implement the dining philosophers problem in C using pthreads, mutex locks, and condition variables.

我正在尝试用C语言实现哲学家就餐问题,使用的是p线程、互斥锁和条件变量。




  • It needs to take a command line argument to specify how long the program should run. I have to use the sleep function to accomplish this.

  • Each philosopher can eat a maximum of 10 meals. Once they reach 10 meals the pthread should terminate.

  • At the end of the set amount of time, the pthreads need to terminate, and the number of meals each philosopher ate should be printed.



I'm having a few problems with the output:

我对输出有几个问题:




  1. Making the main function sleep for the number of seconds entered on the command line doesn't seem to be making the output different.

  2. The majority of the philosophers are starving on most executions of the program.

  3. When I print out when a philosopher is thinking or eating, a 'philosopher 5' is appearing even though there should only be philosophers 0-4.



Here is my code:

下面是我的代码:



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

//Function declarations
void *pickup_forks(void * philosopher_number);
void *return_forks(void * philosopher_number);
void test(int philosopher_number);
int left_neighbor(int philosopher_number);
int right_neighbor(int philosopher_number);
double think_eat_time(void);
void think(double think_time);
void eat(double eat_time);

//Constants to be used in the program.
#define PHILOSOPHER_NUM 5
#define MAX_MEALS 10
#define MAX_THINK_EAT_SEC 3

//States of philosophers.
enum {THINKING, HUNGRY, EATING} state[PHILOSOPHER_NUM];

//Array to hold the thread identifiers.
pthread_t philos_thread_ids[PHILOSOPHER_NUM];

//Mutex lock.
pthread_mutex_t mutex;

//Condition variables.
pthread_cond_t cond_vars[PHILOSOPHER_NUM];

//Array to hold the number of meals eaten for each philosopher.
int meals_eaten[PHILOSOPHER_NUM];

int main(int argc, char *argv[])
{
//Ensure correct number of command line arguments.
if(argc != 2)
{
printf("Please ensure that the command line argument 'run_time' is passed.\n");
}
else
{
//Set command line argument value to variable run_time;
double run_time = atof(argv[1]);

//Initialize arrays.
int i;
for(i = 0; i < PHILOSOPHER_NUM; i++)
{
state[i] = THINKING;
pthread_cond_init(&cond_vars[i], NULL);
meals_eaten[i] = 0;
}


//Initialize the mutex lock.
pthread_mutex_init(&mutex, NULL);

//Join the threads.
for(i = 0; i < PHILOSOPHER_NUM; i++)
{
pthread_join(philos_thread_ids[i], NULL);
}

//Create threads for the philosophers.
for(i = 0; i < PHILOSOPHER_NUM; i++)
{
pthread_create(&philos_thread_ids[i], NULL, pickup_forks, (void *)&i);
}

sleep(run_time);

for(i = 0; i < PHILOSOPHER_NUM; i++)
{
pthread_cancel(philos_thread_ids[i]);
}

//Print the number of meals that each philosopher ate.
for(i = 0; i < PHILOSOPHER_NUM; i++)
{
printf("Philosopher %d: %d meals\n", i, meals_eaten[i]);
}

}

return 0;
}

void *pickup_forks(void * philosopher_number)
{
int loop_iterations = 0;
int pnum = *(int *)philosopher_number;

while(meals_eaten[pnum] < MAX_MEALS)
{
printf("Philosoper %d is thinking.\n", pnum);
think(think_eat_time());

pthread_mutex_lock(&mutex);
state[pnum] = HUNGRY;
test(pnum);

while(state[pnum] != EATING)
{
pthread_cond_wait(&cond_vars[pnum], &mutex);
}
pthread_mutex_unlock(&mutex);

(meals_eaten[pnum])++;

printf("Philosoper %d is eating meal %d.\n", pnum, meals_eaten[pnum]);
eat(think_eat_time());

return_forks((philosopher_number));

loop_iterations++;
}
}

void *return_forks(void * philosopher_number)
{
pthread_mutex_lock(&mutex);
int pnum = *(int *)philosopher_number;

state[pnum] = THINKING;

test(left_neighbor(pnum));
test(right_neighbor(pnum));

pthread_mutex_unlock(&mutex);
}

int left_neighbor(int philosopher_number)
{
return ((philosopher_number + (PHILOSOPHER_NUM - 1)) % 5);
}

int right_neighbor(int philosopher_number)
{
return ((philosopher_number + 1) % 5);
}

void test(int philosopher_number)
{
if((state[left_neighbor(philosopher_number)] != EATING) &&
(state[philosopher_number] == HUNGRY) &&
(state[right_neighbor(philosopher_number)] != EATING))
{
state[philosopher_number] = EATING;
pthread_cond_signal(&cond_vars[philosopher_number]);
}
}

double think_eat_time(void)
{
return ((double)rand() * (MAX_THINK_EAT_SEC - 1)) / (double)RAND_MAX + 1;
}

void think(double think_time)
{
sleep(think_time);
}

void eat(double eat_time)
{
sleep(eat_time);
}


Here is an output using 10 seconds:

以下是使用10秒的输出:



~$ gcc dining_philos.c -o dp -lpthread
~$ ./dp 10
Philosoper 1 is thinking.
Philosoper 2 is thinking.
Philosoper 3 is thinking.
Philosoper 4 is thinking.
Philosoper 5 is thinking.
Philosoper 2 is eating meal 1.
Philosoper 4 is eating meal 1.
Philosoper 2 is thinking.
Philosoper 4 is thinking.
Philosoper 2 is eating meal 2.
Philosoper 4 is eating meal 4.
Philosoper 4 is thinking.
Philosoper 2 is thinking.
Philosoper 2 is eating meal 3.
Philosoper 4 is eating meal 5.
Philosoper 2 is thinking.
Philosoper 4 is thinking.

Philosopher 0: 2 meals
Philosopher 1: 0 meals
Philosopher 2: 3 meals
Philosopher 3: 0 meals
Philosopher 4: 5 meals


I'd appreciate any help. Thanks!

如果有任何帮助,我将不胜感激。谢谢!


更多回答
优秀答案推荐

pthread_create passes a pointer as its last argument. That pointer must be valid at the time the thread is run, not just when it is created. You are using a pointer to the loop variable i, which has evaporated.

PthREAD_CREATE传递一个指针作为其最后一个参数。该指针必须在线程运行时有效,而不仅仅是在创建线程时有效。您使用的是指向循环变量i的指针,该变量已消失。



Also not sure why you are calling pthread_join before pthread_create, but I expect it is returning errors (which you aren't checking).

我也不确定为什么要在调用pthREAD_CREATE之前调用pthREAD_JOIN,但我希望它会返回错误(您没有检查错误)。



I am a little late but for later references 3. problem occurs because you are losing the data when creating philosophers. Try making array and send arrays data address and problem solved

我来晚了一点,但供以后参考3.出现问题是因为您在创建哲学家时丢失了数据。尝试制作数组和发送数组数据地址并解决问题


更多回答

Ok. I created another array that holds the philosopher numbers and passed the ith index of that array for philosopher i in pthread_create. That seems to have done the trick. Thank you!

好的。我创建了另一个保存哲学家编号的数组,并在pthline_create中传递了该数组的第i个索引。这似乎已经奏效了。谢谢!

I don’t know what that means

我不知道那是什么意思

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

您的答案可以通过其他支持信息来改进。请编辑以添加更多详细信息,如引用或文档,以便其他人可以确认您的答案是正确的。你可以在帮助中心找到更多关于如何写出好答案的信息。

27 4 0