Data Races
There is a somewhat technical definition of a data race in C++:
- Two or more threads access the same memory.
- Atleast one access is a write
- The threads do not synchronize with each other.
A data-race is undefined behavior according to the standard. In practice, a data-race results in an incorrectl, possibly random value of an object being read or written depending on how that object is used in your program.
Avoiding data-races is all about the visibility of memory and the changes made to that memory. When two threads synchronize with each other, the programmer has some guarantees about which memory changes made by one thread are visible to the other thread. The memory for a process is not a monolithic thing, such that all threads in the process see the same thing.
#include <iostream>
#include <thread>
#include <vector>
#include <algorithm>
#include <numeric>
#include <utility>
int main()
{
std::vector credits{10.0, 20.0, 30.0, 40.0, 50.0};
std::vector debits{ -10.0, -20.0, -30.0, -40.0, -50.0 };
double total_credits{ 0.0 };
double total_debits{ 0.0 };
double net_balance{ 0.0 };
std::thread credits_thread{
[&credits, &total_credits]() mutable {
= std::accumulate(credits.begin(), credits.end(), 0.0);
total_credits }
};
std::thread debits_thread{
[&debits, &total_debits]() mutable {
= std::accumulate(debits.begin(), debits.end(), 0.0);
total_debits }
};
/* Calculate the net balance */
for (auto credit : credits)
+= credit;
net_balance
for (auto debit : debits)
+= debit;
net_balance
.join();
credits_thread.join();
debits_thread
std::cout << "\n" << "Credit = " << total_credits;
std::cout << "\n" << "Debit = " << total_debits;
std::cout << "\n" << "Net Balance = " << net_balance;
return 0;
}
The calculation of total credits, total debits and net balance quantities can take a while. So, we create a background thread to compute credits and debits