Producer Consumer 仅用 1 个信号量同步
Producer Consumer synchronization with only 1 semaphore
在Producer-Consumer problem中,标准方案使用3个信号量。
但是,我想知道我们是否可以只使用 1 个信号量:
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)
}
}
这个解决方案和标准解决方案一样好吗??
供参考的标准溶液:
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)
}
}
“标准解决方案”不必使用 3 个信号量。即使是您链接的维基百科文章也有一个双信号量解决方案,适用于只有一个生产者和一个消费者的情况:
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);
}
}
具有单个信号量的解决方案不是很好,因为当您真正想要时它们只给您一个等待条件——“免费等待 space”和“等待某个项目”。你不能用一个信号量做这两件事。
无论如何,您的解决方案并没有错,只是效率很低,因为在任何给定时刻,只有一个生产者或一个消费者可以 运行。这本质上是单线程代码,只有锁和线程之间的上下文切换。所以它比实际的单线程代码效率更低。
还有一件事 - 物品生产和消耗通常不是关键部分的一部分。当项目正在被消费或生产时,另一个线程可以 运行。只有在使用缓冲区时才需要互斥。
在Producer-Consumer problem中,标准方案使用3个信号量。
但是,我想知道我们是否可以只使用 1 个信号量:
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)
}
}
这个解决方案和标准解决方案一样好吗??
供参考的标准溶液:
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)
}
}
“标准解决方案”不必使用 3 个信号量。即使是您链接的维基百科文章也有一个双信号量解决方案,适用于只有一个生产者和一个消费者的情况:
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);
}
}
具有单个信号量的解决方案不是很好,因为当您真正想要时它们只给您一个等待条件——“免费等待 space”和“等待某个项目”。你不能用一个信号量做这两件事。
无论如何,您的解决方案并没有错,只是效率很低,因为在任何给定时刻,只有一个生产者或一个消费者可以 运行。这本质上是单线程代码,只有锁和线程之间的上下文切换。所以它比实际的单线程代码效率更低。
还有一件事 - 物品生产和消耗通常不是关键部分的一部分。当项目正在被消费或生产时,另一个线程可以 运行。只有在使用缓冲区时才需要互斥。