Consider the following code:
#include <atomic>
#include <iostream>
#include <thread>
std::atomic<int> x, y;
std::atomic<int> r1, r2;
void f()
{
r1 = y.load();
x = r1.load();
}
void g()
{
r2 = x.load();
y = 42;
}
int main()
{
x = 0;
y = 0;
r1 = 0;
r2 = 0;
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
std::cout << r1 << " " << r2 << std::endl;
}
- If I compile this code with
compilers/linux-x86_64-2.10.1/gnu7.1.0/bin/g++ -fsanitize=thread -O3 -std=c++11 main.cpp -o a.out
,TSan
does not provide any warnings and/or threading errors. - However, this code is allowed to produce both
42 0
and0 0
as output.- If
g()
is executed beforef()
starts, thenr1 = y.load()
will have a value of42
- If
g()
is not executed beforef()
starts, thenr1 = y.load()
will have a value of0
.
- If
- Is this something that I should be expecting
TSan
to catch, or are my expectations completely wrong here?- If my expectations are wrong, what can be done (other than code inspection, which can be very difficult for larger code bases) to find bugs such as this?
- In the event that there should be some error thrown, is there some specific option that I am perhaps missing (I'm using all defaults as specified in the document here)?
Tsan
(a third-party library provided as part of Clang and is back-ported to GCC) to provide an error message indicating a potential threading issue. – Shaunnastd::atomic<T>
ensures reading/writing theT
is atomic. Is the compiler allowed to reorder the statements off()
andg()
, since they're not depending on eachother? (all variables being42
) – SolmizationThreadSanitizer
(aka TSan) is a data race detector for C/C++." There is no data races here, in no way can one of your variable be access by the two threads at the same time. If you want to ensure order of operations, usestd::memory_order
. – Tract