死锁阻止

时间:2016-04-12 17:55:26

标签: c linux deadlock

需要帮助如何防止我写的打击代码的死锁。或任何建议我需要修复代码以摆脱死锁? 当我在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);
}

1 个答案:

答案 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作为参数传递给它们的函数。这种情况可能发生:

  • Thread0执行sem_wait(&(sticks[0]));
  • 上下文切换:thread1执行sem_wait(&(sticks[1]));
  • thread1执行sem_wait(&(sticks[(1+1) % 2 == 0])); // this blocks because thread0 has already sem_wait'ed this semaphore to 0
  • 上下文切换:thread0执行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故障有关。