Are there race conditions in this producer-consumer implementation?

喜欢而已 提交于 2019-12-10 20:33:35

问题


In section 3.4.1 of Operating System Concepts (Silberschatz, 9th edition), the authors present the producer-consumer problem and give the following implementation that uses a circular buffer (page 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
}

The book says:

One issue this illustration does not address concerns the situation in which both the producer process and the consumer process attempt to access the shared buffer concurrently.

I do not see a situation where the producer and consumer would access the same buffer element simultaneously.

My question is: if the producer and consumer ran in two threads, are there race conditions or other synchronization problems in this implementation?


回答1:


There is a lot of possibilities

  1. The most obvious: if there are 2 producer producing data. Assuming there is only 1 free space in the buffer, both producer thread can get pass the while (in + 1) % BUFFER SIZE) == out and try to put to the buffer. This can lead to corrupted buffer or missing data

  2. Even there is only 1 consumer and 1 producer, there are still some less obvious problem. For example, compiler may rearrange the lines

    buffer[in] = next_produced;
    in = (in + 1) % BUFFER SIZE;
    

    to make the update of in happen earlier than update of buffer, which cause the consumer accessing uninitialized data.




回答2:


There is no guarantee that a write to buffer[x] would be seen before a modification of in or out

So assuming only one reader and one writer, then the in, out variables are each modified in a single thread.

buffer[in] = next_produced;
in = (in + 1) % BUFFER SIZE;

Could be seen mis-ordered in the reader, causing the reader to see in moved, but the old value of buffer[in]

Item next_consumed = buffer[out];
out = (out + 1) % BUFFER SIZE;

Could be misordered by the compiler, or the processor, allowing the producer to write into the full queue overwriting the value of buffer[out] before the next_consumed has read the value.



来源:https://stackoverflow.com/questions/34805289/are-there-race-conditions-in-this-producer-consumer-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!