Comment by tialaramex
8 hours ago
Rust doesn't promise that your safe Rust doesn't have race conditions only specifically that it doesn't have the one very weird kind of race condition from computers with no analogue to the real world, a Data Race.
An ordinary race condition would be e.g. you put the cat out of the front door, then you walk to the kitchen and close that door - well, the cat might race around the outside of the house and get in first. Our world has race conditions, Rust doesn't solve them, take appropriate care.
A data race is much stranger, it's caused by a difference between how humans think about programming ("Sequential consistency" ie time's arrow X causes Y, therefore Y happens after X) and how the machine works (a modern multi-core computer does not exhibit this consistency) maybe you and your house mate both pick up the cat and she tries to put it out the kitchen door, you try to put it out the front door, this seems to work fine mostly but then on Tuesday the cat explodes, everything is covered in cat fur, messy. Rust actually has a whole layer of extra stuff beyond the aliasing-XOR-mutability to prevent this mistake because humans struggle to reason properly about software which loses sequential consistency so it almost doesn't matter what it "means" if this is lost.
> In logic, equivocation ("calling two different things by the same name") is an informal fallacy resulting from [...] knowingly and deliberately using words in a different sense than the one the audience will understand.
Of course I mean data race, most people in such a thread will implicitly understand that is the race meant. Nobody building a webshop with limited supplies wants to prevent "first come first served", it barely makes sense to think about preventing that kind of race
Data races have obvious real world analogues, they are just so obvious people naturally synchronize. You can look over someone's shoulder while they update a paper master copy and observe data tearing as they erase a field and start writing in another value while that is inconsistent with the rest of the form. It is easy to see that data is being modified and wait until the writer is complete instead of memorizing a partial update and walking away to make decisions on the basis of the incomplete information. A good mutex/rwlock is like having a private separate room to go into to make the update so that no overeager person can even observe the partial update (some languages have non callback style mutexes so there the mutex/lock is the analogue of the visual cue that someone is performing the update). I don't find this at all strange to consider. In a concurrent system it is just all too easy to forget that there are other threads (analogue of people) reading/modifying at the same time. So rust makes that manifest through the borrow checker and it becomes obvious.
Rust prevents more than just data races. Even in single threaded code, if you have a reference to a struct (without explicitly choosing interior mutability), you are guaranteed that its value has not changed since the last time you read it, despite other parts of the code having a reference to it. You don't need to make defensive copies. Some people may find this useful, but generally it won't be enough to convince someone to drop their current language in favor of rust. This transfers into multi-threaded code as well: only a single thread can make modifications to a struct through a reference xor as many threads as you want can read from the struct with references. You can easily write go/java/python programs that have these features and so don't feature data races, but they are difficult to reason about: how do you know that there is only a single reference featuring mutation or many threads only reading? The answer requires non-local knowledge which is difficult to reason about and this is enough for some people to consider rust where the answer is local (defined by the variable).