需要帮助如何防止我写的打击代码的死锁。或任何建议我需要修复代码以摆脱死锁? 当我在Linux上运行时,我遇到了分段错误(核心转储)。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#include <semaphore.h>
int cnt;
int *bites;
int *old_bites;
sem_t *sticks;
void *roger(void *arg) {
int rog = *(int*)arg;
for(;;) {
sem_wait(&(sticks[rog])); // left
sem_wait(&(sticks[(rog + 1) % cnt])); // right
bites[rog]++;
sem_post(&(sticks[(rog + 1) % cnt])); // right
sem_post(&(sticks[rog])); // left
}
pthread_exit(NULL);
return NULL;
}
int main(int argc, char *argv[]) {
int i;
pthread_t *rogers;
int *pos;
cnt = (int)strtol(argv[1], NULL, 10);
rogers = (pthread_t *)calloc(cnt, sizeof(pthread_t));
pos = (int *)malloc(cnt * sizeof(int));
bites = (int *)calloc(cnt, sizeof(int));
old_bites = (int *)calloc(cnt, sizeof(int));
sticks = (sem_t *)calloc(cnt, sizeof(sem_t));
for(i = 0; i < cnt; i++) {
sem_init(&(sticks[i]), 0, 1);
}
for(i = 0; i < cnt; i++) {
pos[i] = i;
pthread_create(&(rogers[i]), NULL, roger, (void *)&pos[i]);
}
for(;;) {
bool dead = true;
usleep(50000);
for(i = 0; i < cnt; i++) {
if(bites[i] != old_bites[i]) {
dead = false;
}
}
if(dead) {
exit(EXIT_SUCCESS);
}
for(i = 0; i < cnt; i++) {
printf("%8X", bites[i]);
}
printf("\n");
for(i = 0; i < cnt; i++) {
old_bites[i] = bites[i];
}
}
for(i = 0; i < cnt; i++) {
pthread_join(rogers[i], NULL);
}
for(i = 0; i < cnt; i++) {
sem_destroy(&(sticks[i]));
}
exit(EXIT_SUCCESS);
}
答案 0 :(得分:0)
是的,我希望这会陷入僵局。我不知道你为cnt
使用了什么,但是让我们假装它1.在这种情况下,只会创建一个线程。该帖子将sem_wait(&(sticks[0]));
。然后在下一行中sem_wait(&(sticks[(0+1) % 1 == 0]));
。由于您的信号量的初始值为1,因此您不能在没有sem_post
的情况下两次等同一个信号量。因此,该线程将永远等待它无法达到的sem_post
,因为它sem_wait
。
现在考虑cnt > 1
(让我们只说cnt == 2
以使其更简单)的情况。这将生成thread0和thread1,其中0和1作为参数传递给它们的函数。这种情况可能发生:
sem_wait(&(sticks[0]));
sem_wait(&(sticks[1]));
sem_wait(&(sticks[(1+1) % 2 == 0])); // this blocks because thread0 has already sem_wait'ed this semaphore to 0
sem_wait(&(sticks[(0+1) % 2 == 1])); // this blocks because thread1 has already sem_wait'ed this semaphore to 0
现在,您可以让每个帖子等待另一个sem_post
,然后才能继续==&gt;僵局。我希望这个场景可以扩展cnt
的值,但会导致死锁的情况会变得更加复杂。
为什么使用2个信号量来保护单个资源?这个理论对我来说听起来不对。你用这种方法失去了原子性(如果我明显错了,请纠正我。)
此外,您的bites
数组也存在竞争条件。主线程在从中读取之前不会观察同步。这可能与seg故障有关。