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
- Complete list of C programs
- Set up your C development environment
- Best online C compilers to run code instantly
Further reading: The C Programming Language by Kernighan & Ritchie — the definitive C reference.