如何退出简单的生产者-消费者问题

| 我正在尝试制定一个简单的生产者-消费者计划。我有以下代码:
//global variable g_lastImage is declared as:
volatile int g_lastImage = 0;

void producer(void) {
    int i = 0;
    while (1) {     
        sem_wait(&g_shm->PSem);
        printf(\"I:%d\\n\",i);
        if (i == 5) {
            g_lastImage = 1;
            printf(\"It\'s time to say goodbye!\\n\");
            sem_post(&g_shm->ChSem);
            return;
        }
        printf(\"producing\\n\"); 
        i++;
        sem_post(&g_shm->ChSem);
    }
}


void consumer(void) {
    while (1) {
        sem_wait(&g_shm->ChSem);
        if (g_lastImage) {
            printf(\"Bye!\\n\");
            return;
        }
        printf(\"consuming\\n\");
        sem_post(&g_shm->PSem);
    }
}

int main() {
    alloc(); /*allocates shared memory and two semaphores, 
                  ChSem on initial counter value 0 and PSem on value 1*/
    int processes = 1; //let\'s start with one process only just for now
    int id = 0, i = 0, status;

    for (i = 0; i < processes; i++) {
        id = fork();
        if (id < 0) {
          perror (\"error\\n\");
          exit(1);
        } else if (id == 0) {
          consumer();
          printf(\"child exits\\n\");
          exit(0);
        }
    }
    producer();

    for (i = 0; i < processes; ++i) {
        wait(&status);
    }
    return 1;
}
不幸的是,这段代码以死锁结尾。我有这个输出:
I:0
producing
consuming
I:1
producing
consuming
I:2
producing
consuming
I:3
producing
consuming
I:4
producing
consuming
I:5
It\'s time to say goodbye!
consuming
//deadlock - nothing written 
请注意,没有写出“再见!”。另一方面,额外的“消费”是。该解决方案有什么问题?使用全局变量检测结束不是可以的吗?无法弄清楚... 谢谢您的任何想法。 编辑: 根据您的建议,我将局部变量的分配更改为volatile并添加了\'\\ n \',但问题仍然存在。     
已邀请:
您也必须共享您的标志,这可以按您预期的方式工作:
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/mman.h>

struct Shared
{
    sem_t PSem ;
    sem_t ChSem ;
    int g_lastImage ;
} * g_shm ;

void producer(void) {
    int i = 0;
    while (1) {     
        sem_wait(&g_shm->PSem);
        printf(\"I:%d\\n\",i);
        if (i == 5) {
            g_shm->g_lastImage = 1;
            printf(\"It\'s time to say goodbye!\\n\");
            sem_post(&g_shm->ChSem);
            return;
        }
        printf(\"producing\\n\"); 
        i++;
        sem_post(&g_shm->ChSem);
    }
}


void consumer(void) {
    while (1) {
        sem_wait(&g_shm->ChSem);
        if (g_shm->g_lastImage) {
            printf(\"Bye!\\n\");
            return;
        }
        printf(\"consuming\\n\");
        sem_post(&g_shm->PSem);
    }
}

int main()
{
    g_shm = mmap( NULL , sizeof( struct Shared ) , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS , -1 , 0 );
    sem_init( & g_shm->PSem , 1 , 1 );
    sem_init( & g_shm->ChSem , 1 , 0 );
    g_shm->g_lastImage = 0 ;

    int processes = 1;
    int id = 0, i = 0, status;

    for (i = 0; i < processes; i++)
    {
        id = fork();
        if (id < 0) {
          perror (\"error\\n\");
          exit(1);
        } else if (id == 0) {
          consumer();
          printf(\"child exits\\n\");
          exit(0);
        }
    }
    producer();

    for (i = 0; i < processes; ++i)
    {
        wait(&status);
    }
    return 1;
}
    
volatile在这里无济于事,因为您需要分叉处理。这将导致g_lastImage的副本,因此,调用producer()的父进程将更改其自身的g_lastImage值,而子进程(在fork时获得该变量的副本)的子进程将始终具有g_lastImage == 0,因此您最终陷入僵局。您也可以将g_lastImage的分配也插入信号量的分配中,因为看来您已经正确分配了它们,以便将它们放入poth进程中;)     

要回复问题请先登录注册