In C 11, I create 100 threads, every thread call Test::PushFunc, add local static variable index, insert to a local set variable localMap.
In theory, index is stored in Initialized Data Segment Memory and was added by every thread in program running time. Following line
assert(it == localMap.end());
is reasonable because of index to be inserted into localMap is never repeated.
But in practice, program is coredump in assert randomly. Can U tell me why ? Thanks.
#include <set>
#include <iostream>
#include <thread>
class Test {
public:
std::set<std::string> localMap;
void PushFunc()
{
static uint64_t index = 0;
while (true) {
std::cout << "index : " << index << "\n";
index;
const auto& s = std::to_string(index);
const auto& it = localMap.find(s);
assert(it == localMap.end()); //! coredump here
localMap.insert(s);
if (index > 20000000) {
break;
}
}
}
};
int main ()
{
std::vector<std::thread> processThreads;
for (int i = 0; i < 100; i) {
processThreads.emplace_back(
std::thread([]()
{
Test t;
t.PushFunc();
}
));
}
for(auto& thread : processThreads){
thread.join();
}
}
CodePudding user response:
But in practice, program is coredump in assert randomly. Can U tell me why ?
Because you have a data race -- multiple threads are trying to read and write the same variable without any synchronization.
The index
is a global variable. You need to guard access to it with a mutex.
Udate:
But localMap is not a global variable, data race cannot explain one index repeated twice.
- A program with a data race (undefined behavior) can produce any result.
- Yes, it can.
Consider the following instruction interleaving (time goes downwards):
- T1 loads
index
into register (say5
). - T2 loads
index
(5
again) - T1 increments
index
to6
, stores"6"
into its map - T1 loads
6
, incrementsindex
to7
, stores"7"
into its map - T2 "increments" index to
6
, stores"6"
into its own map - T1 loads
6
, increments it to7
, tries to store"7"
into its map ==> assertion failure!
The issue is that index
is not an atomic operation, and (without mutex) other threads may interfere with it.