C Program to solve the producer consumer problem

C Program to Solve the Producer-Consumer Problem Using Semaphores

The producer-consumer problem (also called the bounded-buffer problem) is a classic process synchronization problem. A producer process generates data items while a consumer process reads them; a semaphore enforces the ordering so the consumer never reads ahead of the producer.

Note: This program uses POSIX System V semaphores (<sys/sem.h>) and requires Linux. It will not compile on macOS or Windows without modification.

How It Works

  • A semaphore is initialized to 0 (consumer blocks until producer signals).
  • fork() creates child (consumer) and parent (producer) processes.
  • Producer: prints an item, increments semaphore (sem_op = +1), sleeps 2 s.
  • Consumer: decrements semaphore (sem_op = −1, blocks if 0), prints item, sleeps 3 s.

C Program (Linux)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

/* union semun is not defined in glibc headers — define it manually */
#if defined(__linux__)
union semun {
    int              val;
    struct semid_ds *buf;
    unsigned short  *array;
};
#endif

#define NUM_LOOPS 20

int main(void)
{
    int sem_set_id, child_pid, i, rc;
    union semun sem_val;
    struct sembuf sem_op;
    struct timespec delay;

    sem_set_id = semget(IPC_PRIVATE, 1, 0600);
    if (sem_set_id == -1) {
        perror("main: semget");
        exit(1);
    }
    printf("Semaphore set created, semaphore set id '%d'.\n", sem_set_id);

    sem_val.val = 0;
    rc = semctl(sem_set_id, 0, SETVAL, sem_val);
    if (rc == -1) {
        perror("main: semctl SETVAL");
        exit(1);
    }

    child_pid = fork();
    switch (child_pid) {
        case -1:
            perror("fork");
            exit(1);

        case 0:  /* consumer */
            for (i = 0; i < NUM_LOOPS; i++) {
                sem_op.sem_num = 0;
                sem_op.sem_op  = -1;
                sem_op.sem_flg = 0;
                semop(sem_set_id, &sem_op, 1);
                printf("consumer: '%d'\n", i);
                fflush(stdout);
                sleep(3);
            }
            break;

        default:  /* producer */
            for (i = 0; i < NUM_LOOPS; i++) {
                printf("producer: '%d'\n", i);
                fflush(stdout);
                sem_op.sem_num = 0;
                sem_op.sem_op  = 1;
                sem_op.sem_flg = 0;
                semop(sem_set_id, &sem_op, 1);
                sleep(2);
                if (rand() > 3 * (RAND_MAX / 4)) {
                    delay.tv_sec  = 0;
                    delay.tv_nsec = 10;
                    nanosleep(&delay, NULL);
                }
            }
            break;
    }

    return 0;
}

Sample Output

Semaphore set created, semaphore set id '557068'.
producer: '0'
consumer: '0'
producer: '1'
consumer: '1'
producer: '2'
...

The consumer always lags behind the producer because the semaphore prevents it from running until the producer signals.

Compile and Run (Linux)

gcc producer_consumer.c -o producer_consumer
./producer_consumer

Key Fixes in This Version

Original issue Fix
union semun undefined Defined manually — glibc removed it from headers per POSIX rules
printf string split across lines with .n Merged into one string with \n
Literal n in printf format strings Replaced with \n
No semctl error check Added perror + exit on failure

More C Programs

Further reading: The C Programming Language by Kernighan & Ritchie — the definitive C reference.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>