C 使用信号量解决死锁

C 使用信号量解决死锁,c,operating-system,posix,semaphore,C,Operating System,Posix,Semaphore,我试图用C语言中的信号量来解决哲学家吃饭的问题。下面是我的代码。在代码中,每个筷子都由一个信号量表示。每个哲学家都是一个过程。我使用atmost 4筷子可以在任何给定时间处于“拾取”状态的概念,以避免死锁。这就是我将dt设置为4的原因。请告诉我下面的代码是否正确,逻辑是否正确 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sched.h> #include

我试图用C语言中的信号量来解决哲学家吃饭的问题。下面是我的代码。在代码中,每个筷子都由一个信号量表示。每个哲学家都是一个过程。我使用atmost 4筷子可以在任何给定时间处于“拾取”状态的概念,以避免死锁。这就是我将dt设置为4的原因。请告诉我下面的代码是否正确,逻辑是否正确

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <signal.h>
#include <sys/wait.h>
#include <time.h>
#include <semaphore.h>
#define STACKSIZE 10000
#define NUMPROCS 5
#define ROUNDS 10

sem_t dt,c1,c2,c3,c4,c5;

int child (void * philNum) {
    int* phil1 = (int *)philNum;
    int phil = *phil1;
    int i = 0 ;

    for ( ; i < ROUNDS ; i ++ ) {
        switch(phil){

            case 1:
                sem_wait(&dt);
                sem_wait(&c1);
                sem_wait(&c5);
            case 2:
                sem_wait(&dt);
                sem_wait(&c1);
                sem_wait(&c2);
            case 3:
                sem_wait(&dt);
                sem_wait(&c3);
                sem_wait(&c2);
            case 4:
                sem_wait(&dt);
                sem_wait(&c4);
                sem_wait(&c3);
            case 5:
                sem_wait(&dt);
                sem_wait(&c4);
                sem_wait(&c5);
            default:
                perror(NULL);
                exit(1);
        }

        // Start of critical section -- 
        int sleeptime = rand()%20000 ;
        if ( sleeptime > 10000 ) usleep(sleeptime) ;

        // exit protocol here
        switch(phil){

            case 1:
                sem_post(&dt);
                sem_post(&c1);
                sem_post(&c5);
            case 2:
                sem_post(&dt);
                sem_post(&c1);
                sem_post(&c2);
            case 3:
                sem_post(&dt);
                sem_post(&c3);
                sem_post(&c2);
            case 4:
                sem_post(&dt);
                sem_post(&c4);
                sem_post(&c3);
            case 5:
                sem_post(&dt);
                sem_post(&c4);
                sem_post(&c5);
            default:
                perror(NULL);
                exit(1);
        }

    }
    return 0 ;
}

int main ( int argc, char ** argv ) {
    int i, num ;
    int *pt= (int *)malloc(sizeof(int));
    void * p ;
    srand(time(NULL));
    sem_init(&c1,1,1);
    sem_init(&c2,1,1);
    sem_init(&c3,1,1);
    sem_init(&c4,1,1);
    sem_init(&c5,1,1);
    sem_init(&dt,1,4); //only 4 chopsticks can be picked up at a time. 5th one has to wait anyways as he cant eat with one chopstick
    for ( i = 0 ; i < NUMPROCS ; i ++ ) {
        p = malloc(STACKSIZE) ;
        if ( p == NULL ) {
            printf("Error allocating memory\n") ;
            exit(1) ;
        }
        *pt = i+1;

        int c = clone(child,p+STACKSIZE-1,CLONE_VM|SIGCHLD,(void *)pt,NULL) ;
        if ( c < 0 ) {
            perror(NULL) ;
            exit(1) ;
        }
    }
    for ( ; i > 0 ; i -- ) wait(NULL) ;

    return 0 ;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义堆栈大小10000
#定义NUMPROCS 5
#定义第10轮
扫描电镜,c1,c2,c3,c4,c5;
int子对象(void*philNum){
int*phil1=(int*)philNum;
int-phil=*phil1;
int i=0;
对于(;i10000)usleep(睡眠时间);
//退出协议在这里
交换机(菲尔){
案例1:
sem_post(&dt);
sem_post(&c1);
sem_岗位(c5级);
案例2:
sem_post(&dt);
sem_post(&c1);
sem_post(&c2);
案例3:
sem_post(&dt);
sem_post(&c3);
sem_post(&c2);
案例4:
sem_post(&dt);
sem_post(&c4);
sem_post(&c3);
案例5:
sem_post(&dt);
sem_post(&c4);
sem_岗位(c5级);
违约:
perror(空);
出口(1);
}
}
返回0;
}
int main(int argc,字符**argv){
int i,num;
int*pt=(int*)malloc(sizeof(int));
void*p;
srand(时间(空));
sem_init(&c1,1,1);
sem_init(&c2,1,1);
sem_init(&c3,1,1);
sem_init(&c4,1,1);
sem_init(&c5,1,1);
sem_init(&dt,1,4);//一次只能拿起4根筷子。第五,一个人无论如何都要等,因为他不能用一根筷子吃饭
对于(i=0;i0;i--)等待(NULL);
返回0;
}
我在这里看到一个问题(但它与您正在处理的问题的并行性无关):

在您的
克隆
呼叫之前。基本上,进程的每个克隆都将有相同的随机种子。因此,任何对
rand
的调用,假设它们以相同的顺序出现,都将产生相同的结果“随机”数

您可能应该做的是使随机种子依赖于进程ID,并在克隆出各种进程后进行初始化。这样你就会得到你期望的随机行为


至于整个算法的正确性。。。你试过运行它吗?

你的案子失败了。

嗯。。有趣的是,我们在我的操作系统和并发编程课上也遇到了同样的问题。。。这是克利夫兰的一个常见问题,也是许多CS课程中的一个主要例子。这不在本课程中cleveland@billy无论如何,如果解决方案是相同的,这是一个剽窃的案例,因为这是我的原始解决方案:)我试着运行它。它编译时没有错误,但只是挂起。您如何知道它是否挂起?这里似乎没有什么事情发生,但让每个人都永远奔跑…@比利。不,循环只运行10次。请查看(;isrand(time(NULL));