我有一个经典的生产者/消费者问题。生产者的代码是:
#define BUFFER_SIZE 10
while (true) {
/* Produce an item */
while (( (in + 1) % BUFFER_SIZE) == out)
; /* do nothing -- no free buffers */
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
}
消费者是:
while (true) {
while (in == out)
; // do nothing -- nothing to consume
// remove an item from the buffer
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
return item;
}
这很好但问题是当前八个元素被填满in=9
和out=0
时,生产者就坐在那里并且没有填充最后一个(第九个)元素。如果说in=4
和out=5
,也会发生这种情况。在每种情况下,即使一个插槽仍为空,一个元素仍为空,并且队列看起来是“满的”。
我可以提出一些复杂的检查,但我需要知道是否有一个干净的解决方案来填充整个队列。我尝试先增加,然后放入item
,但也会遇到类似的问题。 (-1
和in
的{{1}}初始化也不起作用。
答案 0 :(得分:1)
有关此主题的信息,请参阅Wikipedia。最简单的解决方案似乎是:
in == out
则缓冲区为空; if in == out - 1
,缓冲区已满out
替换为num_unread_items
;执行简单的数学运算,从out
和num_unread_items
in
...但是还有其他与计算读数和数量相关的选项。写操作(在单独的变量中或直接在in
和out
);或跟踪当前in
和out
之外的最后一次操作是读取还是写入,这允许您消除缓冲区满/缓冲区空案例的歧义。
答案 1 :(得分:1)
在大学的操作系统开发课程中,我有一位兼职教师声称不可能拥有一个只能使用缓冲区中所有N个元素的纯软件解决方案。 我证明他错了我决定称之为赛道解决方案(受到我喜欢跑道的启发)。
在赛道上,您不仅限于400米比赛;比赛可以包括一圈以上。如果两个跑步者是颈部和颈部会发生什么 在比赛中?你怎么知道他们是否被束缚,或者一个跑步者是否已经打了另一个?答案很简单:在比赛中,我们不监控跑步者的位置 在轨道上;我们监控每个跑步者所经过的距离。因此,当两个跑步者是颈部和颈部时,我们可以在一个领带和一个跑步者之间消除歧义 把对方舔了一下。
因此,我们的算法有一个N元素数组,并管理一个2N竞赛。在他们完成各自的2N比赛之前,我们不会重新启动生产者/消费者的计数器。 我们不允许生产者超过消费者超过一圈,我们不允许消费者领先于生产者。 实际上,我们只需要监控生产者和消费者之间的距离。
代码如下:
Item track[LAP];
int consIdx = 0;
int prodIdx = 0;
void consumer()
{ while(true)
{ int diff = abs(prodIdx - consIdx);
if(0 < diff) //If the consumer isn't tied
{ track[consIdx%LAP] = null;
prodIdx = (prodIdx + 1) % (2*LAP);
}
}
}
void producer()
{ while(true)
{ int diff = (prodIdx - consIdx);
if(diff < LAP) //If prod hasn't lapped cons
{ track[prodIdx%LAP] = Item(); //Advance on the 1-lap track.
prodIdx = (prodIdx + 1) % (2*LAP);//Advance in the 2-lap race.
}
}
}
自从我最初解决问题以来已经有一段时间了,所以这是根据我最好的回忆。希望我没有忽视任何错误。 希望这有帮助!