3 ms·
While true, it is still generally a mistake to leave a race condition in your code, because your human understanding of the possible interleavings is very unlik
by jerf 7y ago
While true, it is still generally a mistake to leave a race condition in your code, because your human understanding of the possible interleavings is very unlikely to be correct. In addition to the way the code appears to be written, understanding the impact of a race condition requires you to fully understand the memory model in play, fully understanding all compiler optimizations that may have been made, which may include instruction reordering, fully understand all memory alignment issues on all machines you may execute this on and all their little differences, including on machines that don't exist yet that your code may run on in the future, and fully understand the entire stack of code involved in the race condition from the level of abstraction you're using pretty much all the way down to the compiled and optimized assembler. It also makes testing harder... all kinds of testing, automated and otherwise, because whether or not your tests can get to a given part of the state space becomes nondeterministic.
The average developer assessment that some race condition is completely harmless is wrong; there's usually a bug in the complicated state space somewhere.
A performance optimization involving a deliberate race condition should be pretty much your last resort.
Even the obvious ones are often less of a good idea than they may look, like a leaky incrementing counter for logging purposes. You might model that as being unlikely to lose more than a couple of percent, but I've seen cases where it lost the majority of logged events. Granted, this probably won't crash your program, but it can still result in surprisingly deceptive logging.
- jfkebwjsbx 7y agoNot all race conditions are as complex as you make them to be, in particular if they are done on purpose. And many race conditions don't have anything to do with the memory model or compiler optimizations.
- MaxBarraclough 7y ago> And many race conditions don't have anything to do with the memory model or compiler optimizations. For example, poorly structured response-handlers in JavaScript. If the code assumes that request R1 always returns before request R2, things may misbehave if that assumption is violated. That's a race condition, but as you say, it's nothing to do with memory models or compiler trickery, as JavaScript gives you just the one thread (not counting workers).
- deleted 7y ago[deleted]
- throwaway2048 7y agoIf R2 returns before R1 that is still a race condition, but it might not be a bug.
- MaxBarraclough 7y ago> If R2 returns before R1 that is still a race condition That's not correct. Look at chrisseaton's definition. If the observable program behaviour doesn't change depending on the order in which the requests complete, there's no race condition. (In JavaScript this might be done with Promise.all.) You're right that not all race conditions are bugs.
- gildas 7y agoThere is even Promise.race provided for that purpose in JavaScript. You can typically use it to implement a watchdog.
- AnimalMuppet 7y agoParticularly if they are done on purpose??? Can you give an example of when one would (sanely) want to create a race condition?
- chrisseaton 7y agoI don’t think you ever want a race condition for the sake of it but there are many daily cases where you don’t care that it races and fixing it would have terrible downsides. In a distributed system they’re practically unavoidable I think!
- chrisseaton 7y agoI think you might possibly be overstating how complex a race condition needs to be. For example two consumers pushing results to a single result queue is a race condition, because the order in which they arrive depends on timing and is non-deterministic. That's a pretty normal thing to have. Many languages people think of as being safe and high level are extremely racey - Erlang is my go-to example - two processes sending messages to a third is a race. Which message do you get first? It's non-deterministic. But it doesn't have to be a problem.
- isaachier 7y agoWhat you are describing sounds like non-deterministic behavior of a thread-safe primitive, e.g. non-deterministic ordering in a synchronized queue. On the other hand, a true race condition in the queue could mean messages overwriting each other.
- chrisseaton 7y ago> What you are describing sounds like non-deterministic behavior of a thread-safe primitive, e.g. non-deterministic ordering in a synchronized queue. That's what a race condition is - non-deterministic behavior of a thread-safe primitive. > On the other hand, a true race condition in the queue could mean messages overwriting each other. That's a data race, not a race condition.
- deleted 7y ago[deleted]