Reputation: 8576
In the Producer-Consumer problem, the standard solution uses 3 semaphores.
However, I was wondering if we could just use 1 semaphore:
semaphore mutex = 1
procedure producer() {
while (true) {
down(mutex)
if (bufferNotFull()) {
item = produceItem()
putItemIntoBuffer(item)
}
up(mutex)
}
}
procedure consumer() {
while (true) {
down(mutex)
if (bufferNotEmpty()) {
item = removeItemFromBuffer()
consumeItem(item)
}
up(mutex)
}
}
Is this solution as good as the standard one??
The standard solution for reference:
semaphore mutex = 1
semaphore fillCount = 0
semaphore emptyCount = BUFFER_SIZE
procedure producer() {
while (true) {
item = produceItem()
down(emptyCount)
down(mutex)
putItemIntoBuffer(item)
up(mutex)
up(fillCount)
}
}
procedure consumer() {
while (true) {
down(fillCount)
down(mutex)
item = removeItemFromBuffer()
consumeItem(item)
up(mutex)
up(emptyCount)
}
}
Upvotes: 2
Views: 745
Reputation: 30285
The "standard solution" doesn't have to use 3 semaphores. Even the wikipedia article you linked has a two-semaphore solution for cases in which there's a single producer and a single consumer:
semaphore fillCount = 0; // items produced
semaphore emptyCount = BUFFER_SIZE; // remaining space
procedure producer()
{
while (true)
{
item = produceItem();
down(emptyCount);
putItemIntoBuffer(item);
up(fillCount);
}
}
procedure consumer()
{
while (true)
{
down(fillCount);
item = removeItemFromBuffer();
up(emptyCount);
consumeItem(item);
}
}
Solutions with a single semaphore aren't great since they give you just a single wait condition when you actually want to - "wait for free space", and "wait for an item". You can't do both with a single semaphore.
Anyway, your solution isn't wrong, it's just very inefficient since at any given moment only a single producer or a single consumer can run. This is essentially single-threaded code, only with locks and context switches between threads. So it's even less efficient that actual single threaded code.
And one more thing - item production and consumption aren't usually part of the critical section. While the item is being consumed or produced, the other thread can run. We need mutual exclusion only when using the buffer.
Upvotes: 3