Shared memory
The bug that is there when the answer is right
A data race is a property of the program, not of the run. This is the case no test can catch, and the reason this app exists.
12 minutes · data race · happens-before · unsynchronised access
A race is not a failure
Everything else a checker reports is something that went wrong on a particular run: an assertion that failed, a program that stopped. A data race is not like that. It is a fact about the program — two threads touch the same location, at least one of them writes, and nothing in the code puts the two accesses in an order — and it holds whether or not this run misbehaved.
That is exactly the thing testing cannot reach. A racy program can produce the right answer on every interleaving your machine happens to pick, for years. The behaviour it is allowed to produce is a different question from the behaviour you have observed, and only the first one is a property of the code.
The engine answers the first question. It builds the happens-before relation as it runs — a lock released and reacquired orders two threads, an atomic write and an atomic read of it order them, a spawn and a join order them — and anything not ordered by that relation is concurrent. Two concurrent accesses to one location with a write among them are a race, and it says so even when nothing went wrong.