Data Races
-
A "data race" occurs when:
- Two or more threads access the same memory location
- And at least one of the threads modifies it
- And the threads are not synchronized when they access the memory location
-
Only safe if the threads are synchronized
- One thread accesses the memory location at a time
- The other threads have to wait until it is safe for them to access it
- In effect, the threads execute sequentially while they access it
-
A data race causes undefined behavior
- The program is not guaranteed to behave constantly
// unsynchronized threads which make conflicting accesses
// But where is the shared memory location?
#include <iostream>
#include <string>
#include <thread>
void print(std::string str) {
for (int i = 0; i < 5; ++i) {
std::cout << str[0] << str[1] << str[2] << std::endl;
}
}
int main() {
std::thread thr1(print, "abc");
std::thread thr2(print, "def");
std::thread thr3(print, "xyz");
thr1.join();
thr2.join();
thr3.join();
}
Output
- The output will be scrambled up
- What has gone wrong?
- Threads can be interrupted during output
- Other threads can run and write their output
- The output from different threads is interleaved
Data Race Consequences
-
In this program, the data race caused interleaved output
std::coutis a special case- Nothing worse than output interleaving can happen
-
The consequences of a data race can be much more serious
- Incorrect results
- Incorrect program flow
- "Torn" writes and reads
- Objects which are improperly constructed or destroyed