【问题标题】:Resolving dining philosophers deadlock using semaphores使用信号量解决哲学家就餐僵局
【发布时间】:2011-07-09 07:33:31
【问题描述】:

我正在尝试使用 C 中的信号量来解决哲学家就餐问题。下面是我的代码。在代码中,每根筷子都由一个信号量表示。每个哲学家都是一个过程。我使用的概念是,在任何给定时间最多可以有 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 ;
}

【问题讨论】:

  • 嗯.. 有趣的是,我们在我的操作系统和并发编程课上也遇到了同样的问题......这在克利夫兰有什么机会吗?
  • 这是一个常见的问题,也是很多 CS 课程中的主要例子之一。
  • 这不在克利夫兰
  • @billy 无论如何,如果解决方案相同,这是抄袭的案例,因为这是我的原始解决方案:)

标签: c operating-system posix semaphore


【解决方案1】:

您的案件正在失败。

【讨论】:

    【解决方案2】:

    我在这里看到一个问题(但它与您正在处理的问题的并行性并没有真正的关系):

    srand(time(NULL));
    

    在您的clone 电话之前。基本上,您的进程的每个克隆都将具有相同的随机种子。因此,任何对rand 的调用,假设它们以相同的顺序发生,都会产生相同的“随机”数字。

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

    至于整体算法的正确性……你试过运行吗?

    【讨论】:

    • 我尝试运行它。它编译没有错误,但只是挂起
    • 你怎么知道它是否挂起?这里似乎没有发生任何事情,但让每个人都永远奔跑......
    • @Billy。不,循环只运行 10 次。请看 child() 函数
    • for ( ; i
    • @Programmer:请停止要求投票和对试图帮助您的人大喊大叫。人们只要喜欢你的问题就会投票,而不是因为你要求它。此外,向唯一一个努力帮助你的人大喊大叫是非常粗鲁的。
    猜你喜欢
    • 2018-06-02
    • 2017-04-10
    • 2022-12-29
    • 1970-01-01
    • 2021-05-04
    • 2018-01-21
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多