- Concurrent access to shared data may result in data inconsistency.
- Maintaining data consistency requires mechanisms to ensure the orderly execution of cooperating processes.
Problem
Finite buffer shared by producer and consumer
- Producer produces a stream of items and puts them into buffer,
- Consumer takes out stream of items.
Have to deal with producers waiting for consumers when buffer is full, and consumers waiting for producers when buffer is empty.
Producer
while (true) {
/* produce an item and put in nextProduced */
while (count == BUFFER_SIZE); // wait if buffer full
buffer [in] = nextProduced; // store new item
in = (in + 1) % BUFFER_SIZE; // increment IN pointer.
count++; // Increment counter
}Consumer
while (true) {
while (count == 0) ; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
/* consume the item in nextConsumed */
}Race Condition
There is something wrong with this code!
count++could be compiled as a sequence of CPU instructions :register = countregister = register1+1count = register1
count--could be compiled likewise:register2 = countregister2 = register2-1count = register2
- Consider that the producer and consumer execute the
count++andcount--around the same time, such that the CPU instructions are interleaved as follows (withcount=5initially) :
- With an increment and a decrement, in whatever order, we would expect no change to the original value (5), but here we have ended up with 4 ?!?!
A race condition occurs when a systemβs behaviour is dependent on the sequence or timing of other uncontrollable events, leading to unexpected or inconsistent results.