在操作系统概念3.4.1节(Silberschatz,第9版)中,作者介绍了生产者-消费者问题,并给出了以下使用循环缓冲区的实现(第125、126页)。
//Shared variables
#define BUFFER SIZE 10
struct Item;
Item buffer[BUFFER SIZE];
int in = 0, out = 0;
//buffer is empty when in == out
//buffer is full when (in + 1) % BUFFER SIZE == out
//Producer
while (true)
{
Item next_produced = /*produce item here*/;
while (((in + 1) % BUFFER SIZE) == out) ; //do nothing
buffer[in] = next_produced;
in = (in + 1) % BUFFER SIZE;
}
//Consumer
while (true)
{
while (in == out) ; //do nothing
Item next_consumed = buffer[out];
out = (out + 1) % BUFFER SIZE;
//consume the item in next_consumed here
}书上说:
此示例没有解决的一个问题涉及生产者进程和使用者进程同时尝试访问共享缓冲区的情况。
我不认为生产者和使用者会同时访问相同的缓冲区元素。
我的问题是:如果生产者和使用者在两个线程中运行,这个实现中是否存在竞争条件或其他同步问题?
发布于 2016-01-15 06:57:46
有很多可能性
while (in + 1) % BUFFER SIZE) == out并尝试放入缓冲区。这可能导致缓冲区损坏或数据丢失。in的更新比buffer的更新更早,这会导致使用者访问未初始化的数据。发布于 2016-01-15 08:38:31
不能保证在修改buffer[x]或in之前会看到对out的写入。
因此,假设只有一个读取器和一个作者,那么in,out变量都是在一个线程中修改的。
buffer[in] = next_produced;
in = (in + 1) % BUFFER SIZE;在读取器中可以看到错误的顺序,使读者看到的是感动,而旧的值却是bufferin。
Item next_consumed = buffer[out];
out = (out + 1) % BUFFER SIZE;编译器或处理器可能会出错,允许生产者在buffer[out]读取值之前将其写入整个队列,覆盖该值。
https://stackoverflow.com/questions/34805289
复制相似问题