This project implements a solution to the classic Producer-Consumer Problem using Java. The project demonstrates the importance of synchronization in concurrent systems using Semaphores.
The Producer-Consumer problem is a well-known illustration of multi-process synchronization. It involves a finite-size buffer shared by two different process types:
- Producers: Generate data (items) and add them to the buffer.
- Consumers: Remove data from the buffer for processing.
The project addresses two main challenges:
- Overflow: Ensuring producers refrain from adding data while the buffer is full.
- Underflow: Ensuring consumers do not delete data when the buffer is empty.
- Race Conditions: Using synchronization to prevent data corruption or deadlocks.
We use Semaphores to handle synchronization and keep access organized:
mutex: Protects the buffer (Mutual Exclusion).emptySlots: Tracks available space in the buffer.fullSlots: Tracks available items in the buffer.
The program is divided into four main classes:
Buffer.java: The shared class that holds the queue and manages synchronization logic.Producer.java: A thread class that generates and adds items (1 to 10) to the buffer.Consumer.java: A thread class that removes and processes items from the buffer.ProducerConsumerDemo.java: The entry point class that initializes a buffer with a capacity of 5 and starts both threads.
- Waits if the buffer is full using
emptySlots.acquire(). - Locks the queue using
mutex.acquire(). - Adds the item and signals availability using
fullSlots.release().
- Waits if the buffer is empty using
fullSlots.acquire(). - Locks the queue using
mutex.acquire(). - Removes the item and signals a free slot using
emptySlots.release().