4 ms·
There is general agreement that the Java 5 memory model's definition of data races is unsatisfactory. It's overly restrictive of optimizations, it doesn't quite
by jcranmer 3y ago
There is general agreement that the Java 5 memory model's definition of data races is unsatisfactory. It's overly restrictive of optimizations, it doesn't quite match reality, it's utterly confusing (it's like 12 pages where the rest of the memory model is basically just 1 page). The only reason it's not UB in Java is that Java doesn't want any UB; everyone agreed that in C/C++, UB was the best way to handle data races.
C++ does have a form of defined data races, though: relaxed atomics. And if you look at the history of relaxed atomics, from the moment it was first voted into the standard, there's been constant tweaking and kvetching over its unsuitability. I wouldn't recommend trying to understand relaxed atomics any more thoroughly than "you will read some value you wrote into it."
- o11c 3y agoC++ relaxed still serializes accesses to the variable itself, so it is far more useful than mere "defined data races". In particular it's useful for things like counters that always increment, or counters that decrement but which will branch and do another atomic operation when it reaches zero.
- jcranmer 3y agoI was going to mention that relaxed atomics additionally have a requirement that a read always reads the "last" write to that value, but the problem is that the temporal sense of "last" in that sentence only bears a loose resemblance to a typical programmer's sense of time in a program, so I think it may confuse more than it helps. In LLVM IR terms, the largest practical difference to users between unordered (Java) and monotonic (C relaxed) is that unordered is too weak to let an atomicrmw instruction be definable, whereas monotonic is strong enough to let it be defined. In both cases, you still have to be prepared for the possibility that a load is going to read a value that is in some sense stale. (There are a few other differences, e.g., you can reorder load unordered p/load unordered q if p and q are may-alias, but you can't if they're relaxed loads. But that's generally something that only comes up when you're writing optimization passes).