c - 使用 Pthreads 在 C 中就餐哲学家的分段错误
问题描述
我在用餐哲学家的练习中遇到了这个分段错误问题,每个哲学家一个线程,我无法管理。每个线程思考一个随机的时间段,与吃相同。每个哲学家可以用两把叉子吃饭,他必须把两把叉子都挑起来吃。为了避免僵局,我为采摘叉做了一个排序。奇数的哲学家首先选择正确的叉子。我使用了一个全局信号量,我在 main 开始时使用函数 init 对其进行了初始化。请问有人可以帮助我吗?我试图放一些 fprintf(stderr,"HERE\n") 但由于并发性我找不到问题。这是代码
'''
//global array of semaphore
pthread_mutex_t *mtx;
//intialize array of semaphore
void init(pthread_mutex_t *mtx){
mtx=malloc(N*sizeof(pthread_mutex_t));
if(!mtx){
perror("malloc fallita\n");
exit(EXIT_FAILURE);
}
for(int i=0;i<N;i++){
if(pthread_mutex_init(&mtx[i],NULL) != 0){
perror("init fallita\n");
exit(EXIT_FAILURE);
}
}
}
void eat(unsigned int *seed){
long r = rand_r(seed) % 800000;
struct timespec t={0,r};
nanosleep(&t,NULL);
}
void think(unsigned int *seed){
long r = rand_r(seed) % 1000000;
struct timespec t={0,r};
nanosleep(&t,NULL);
}
void *filosofo(void *arg){
unsigned int id = *((unsigned int*)arg);
unsigned int seed=id;
int left = id % N;
int right = id-1;
while(1){
think(&seed);
if(id % 2){ //il filosofo di indice dispari prende prima la forchetta di destra
pthread_mutex_lock(&mtx[right]);
pthread_mutex_lock(&mtx[left]);
eat(&seed);
pthread_mutex_unlock(&mtx[left]);
pthread_mutex_unlock(&mtx[right]);
}else{ //il filosofo di indice pari prende prima la forchetta a sinista
pthread_mutex_lock(&mtx[left]);
pthread_mutex_lock(&mtx[right]);
eat(&seed);
pthread_mutex_unlock(&mtx[right]);
pthread_mutex_unlock(&mtx[left]);
}
}
pthread_exit(NULL);
}
int main(void){
init(mtx);
//array of N philosophers
pthread_t *th;
th = malloc(N*sizeof(pthread_t));
if(!th){
perror("Malloc fallita\n");
exit(EXIT_FAILURE);
}
for(unsigned int i=0;i<N;i++){
if(pthread_create(&th[i],NULL,filosofo,(void*)(intptr_t)i) != 0){
perror("create fallita\n");
exit(EXIT_FAILURE);
}
}
for(unsigned int i=0;i<N;i++){
if(pthread_join(th[i],NULL) == -1){
perror("join fallita\n");
}
}
free(th);
free(mtx);
return 0;
}
'''
解决方案
您需要将init
指针指向一个指向互斥锁的指针以进行初始化。目前,全球mtx
没有改变。
大致方法如下:
void init(pthread_mutex_t **mtx){ // pointer to pointer
*mtx=malloc(N*sizeof(pthread_mutex_t)); // dereference
if(!*mtx){
perror("malloc fallita\n");
exit(EXIT_FAILURE);
}
for(int i=0;i<N;i++){
if(pthread_mutex_init(&(*mtx)[i],NULL) != 0){ // pointer acrobatics
perror("init fallita\n");
exit(EXIT_FAILURE);
}
}
}
然后将指针传递给全局mtx
in main
:
int main(void){
init(&mtx);
我建议以不同的方式命名您的全局互斥锁和本地互斥锁,init
这样就不会再让您感到困惑了。
另外,在这里,您将 的值i
作为 avoid *
传递,而不是传递其地址:
if(pthread_create(&th[i],NULL,filosofo,(void*)(intptr_t)i) != 0){
如果你这样做(我实际上建议避免竞争条件),那么你应该改变filosofo
以同样的方式接受输入:
unsigned int id = (unsigned int)arg;
推荐阅读
- javascript - Ajax - 插入图像
- html - 如何在不改变 CSS (Bootstrap 4) 中的比例的情况下将图像缩放到列宽?
- linux - 在 Linux shell 中读取文本并将某些特定行写入新文件
- python - Sympy 从向量场获取向量
- c# - 当 sum 中的表达式是字符串时,如何在 linq 中进行分组和求和?
- android - Google search alike SearchView
- python - 网络抓取和提取日期
- java - 在 actionListener 内的 hashMap 中添加项目
- php - Google Calendar API - 获取事件
- raspberry-pi - Contiki os and rapsberry PI 3