为什么只有一个生产者和一个消费者时不需要同步缓冲区?

Why no need to synchronize buffer when only have one producer and one consumer?

以下伪代码来自Wiki - producer-consumer problem.

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);
    }
}

我的问题是为什么我们可以在不同步的情况下同时调用putItemIntoBufferremoveItemFromBuffer?为什么这里没有竞争条件?

为什么我们可以在不同步的情况下同时调用 putItemIntoBuffer 和 removeItemFromBuffer?

简短的回答:这是一个伪代码,所以不要按字面意思理解。代码的目的是展示如何同步消费者和生产者,而不是数据访问,就像开头的维基文章所述:

The problem is to make sure that the producer won't try to add data into the buffer if it's full and that the consumer won't try to remove data from an empty buffer.

您引用的伪代码使用信号量解决了这个问题:

Semaphores solve the problem of lost wakeup calls.

在缓冲区大小为 1 的情况下,代码可能会正常运行,没有任何额外的麻烦。但是对于任何缓冲区大小,putItemIntoBuffer()/removeItemFromBuffer() 的实际实现可能会在内部使用锁来访问共享缓冲区,或者可以实现为无锁循环队列,就像下面显示的 producer()/consumer() 函数之一一样文章,即:

volatile unsigned int produceCount = 0, consumeCount = 0;
ItemType buffer[BUFFER_SIZE];

void putItemIntoBuffer(ItemType *item) {
    buffer[produceCount % BUFFER_SIZE] = *item;
    ++produceCount;
}
void removeItemFromBuffer(ItemType *item) {
    *item = buffer[consumeCount % BUFFER_SIZE];
    ++consumeCount;
}

为什么这里没有竞争条件?

访问共享缓冲区可能存在竞争条件,但这不是生产者-消费者问题的要点,因此也不是上述 Wiki 文章的要点。