我遇到以下C代码的问题。代码本身应该创建5个线程来模拟线程正在访问共享数据的Dining Philosophers问题。代码如下:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
//creation of the mutex lock, condition variables, and state
pthread_mutex_t mutex;
pthread_cond_t cond_var[5];
enum{THINKING, HUNGRY, EATING}state[5];
//test if possible to get forks
void test(int pNumber){
//start eating if the adjacent philosophers aren't eating
if((state[(pNumber + 1) % 5] != EATING) && (state[(pNumber + 4) % 5] != EATING)){
state[pNumber] = EATING;
//signal self if test() called by another thread
pthread_cond_signal(&cond_var[pNumber]);
}
}
//used to make the philosopher's forks unavailable
void pickup_forks(int pNumber){
//get lock
pthread_mutex_lock(&mutex);
//set state to hungry
state[pNumber] = HUNGRY;
printf("Philosopher %d is HUNGRY\n", pNumber);
//attempt to begin eating. if unable to, will wait
test(pNumber);
while(state[pNumber] != EATING){
pthread_cond_wait(&cond_var[pNumber], &mutex);
//switched the order of the arguments
}
//release lock
pthread_mutex_unlock(&mutex);
}
//allow neighbors to use philosopher's forks
void release_forks(int pNumber){
//get lock
pthread_mutex_lock(&mutex);
//set own state to thinking
state[pNumber] = THINKING;
//tell adjacent philosophers to try to eat
test(((pNumber + 1) % 5));
test(((pNumber + 4) % 5));
//release lock
pthread_mutex_unlock(&mutex);
}
//used by the thread to run the philosophers
void *runPhilosopher(void *x){
//which philosopher it is
int pNumber = *((int*) x);
//initially thinking
state[pNumber] = THINKING;
printf("Philosopher %d is THINKING\n", pNumber);
//"think" for a random amount of time between 1-3 seconds
int sleepTime = rand() % 3 + 1;
sleep(sleepTime);
//each philosopher eats a total of 5 times
int i = 0;
for(i = 0; i < 5; i++){
//get the forks and begin eating
pickup_forks(pNumber);
//eating time
sleep(2);
//put down forks and resume thinking
release_forks(pNumber);
sleepTime = rand() % 3 + 1;
sleep(sleepTime);
}
printf("Philosopher %d has finished eating\n", pNumber);
}
int main(int argc, char *argv[])
{
pthread_mutex_init(&mutex, NULL);
int i = 0;
for(i = 0; i < 5; i++){
pthread_cond_init(&cond_var[i], NULL);
}
pthread_t tid[5]; //thread id
pthread_attr_t attr; //set of thread attributes
pthread_create(&tid[0], NULL, runPhilosopher, (void *) 0);
pthread_create(&tid[1], NULL, runPhilosopher, (void *) 1);
pthread_create(&tid[2], NULL, runPhilosopher, (void *) 2);
pthread_create(&tid[3], NULL, runPhilosopher, (void *) 3);
pthread_create(&tid[4], NULL, runPhilosopher, (void *) 4);
//wait for threads to finish
for(i = 0; i < 5; i++){
pthread_join(tid[i], NULL);
}
return 0;
}
我使用gedit在Linux虚拟机上。该程序编译正常,但在尝试运行它时,我得到一个“分段错误”错误,这是来自尝试的线程创建,根据gdb。我发现这里没有任何相关问题适用于我的程序。
我尝试过的事情:
有人看到一个我忽略的简单解决方案,还是我的程序存在严重缺陷?我无法理解这个问题是什么,但我完全承认我不熟悉C.任何帮助都将不胜感激!
答案 0 :(得分:4)
你的问题在这里:
int pNumber = *((int*) x);
当你调用pthread_create()
时,你会将一个整数强制转换为指针,然后你将它转换为线程函数中的指针并继续取消引用它。
相反,请尝试
int pNumber = (int) x;
请注意,这可能会导致编译器警告sizeof(int) != sizeof(void*)
。您可能希望先转换为uintptr_t
。
或者,您可以将int
存储在本地变量中,并将其地址传递给pthread_create
。只需确保在包含函数返回之前所有线程都已停止。
或者,您可以malloc
将int
作为成员的结构,并将指针传递给它。