5 ms·
Thread-safety is defined as "the absence of data-races", so technically speaking, saying that Rust is "thread-safe" and saying that it provides "data-race freed
by fluffything 6y ago
Thread-safety is defined as "the absence of data-races", so technically speaking, saying that Rust is "thread-safe" and saying that it provides "data-race freedom", is just two different forms of saying the exact same thing.
The problem is that some people don't know what these mean. I'm not sure why though. Like, I could understand that somebody coming to Rust from Java wouldn't know what "memory safety" means since it is essentially a solution to a problem that Java does not have. But most high-level languages do not protect you from data-races, so this is a problem that Rust does solve and one can run into in most widely-used programming languages (e.g. in Java they are also called data-races).
- mratsim 6y agoThis is not what thread safety means: > Thread safety is a computer programming concept applicable to multi-threaded code. Thread-safe code only manipulates shared data structures in a manner that ensures that all threads behave properly and fulfill their design specifications without unintended interaction. There are various strategies for making thread-safe data structures. (Wikipedia) Data races is only part of the problem. Thread-safe also means that your design is bug-free and you don't have livelocks for example because of how you state machines interact there is a way for them to loop forever in an unexpected way (example, dining philosophers). Similarly, data-race-freedom as provided by Rust is helpful for end users but not for library developers. Developers of concurrent data structures or threading primitives are on their own to sail in the complexities of the C++11 Memory Model (i.e. Acquire/Release) and the compiler cannot verify that you didn't introduce a synchronization bug in your new concurrent queue or event bus.
- TheNorthman 6y agoContinuing from the same Wikipedia page, it mentions three levels of thread safety. Rust support all of them, and can guarantee them at compile time: > _Thread safe_: Implementation is guaranteed to be free of race conditions when accessed by multiple threads simultaneously. > _Conditionally safe_: Different threads can access different objects simultaneously, and access to shared data is protected from race conditions. > _Not thread safe_: Data structures should not be accessed simultaneously by different threads.
- mratsim 6y agoIt does not though? How does Rust proves that your implementation of a Peterson's lock algorithm[1] or Lamport's Bakery algorithm[2] is: - Deadlock-free - Live-lock free - Free of data races Second, how does Rust proves that you are correctly using the relaxed, acquire and release atomics so that your channel implementation is free of data races? You can use Loom[3] but this is guarantee is certainly not provided by the compiler. In short, Rust compiler only addresses memory issues by flat out preventing memory sharing. However, someone has to write those sharing/synchronizing data structures (Channels, Event Bus, Concurrent Hash-Table, ...) and those people have no tools that help them navigate the significant complexity of multithreading that go beyond memory and lifetime bugs. [1]: https://en.wikipedia.org/wiki/Peterson%27s_algorithm#The_algorithm https://en.wikipedia.org/wiki/Peterson%27s_algorithm#The_alg... [2]: https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm [3]: https://github.com/tokio-rs/loom https://github.com/tokio-rs/loom
- TheNorthman 6y agoThat's my mistake. I confused data races and general race conditions, sorry about that :).
- fluffything 6y ago> This is not what thread safety means: > > Thread safety is a computer programming concept applicable to multi-threaded code. Woah woah, hold your horses. Thread-safety is a definition in the specification of the operational semantics of programming languages. It is a precise mathematical term used in proofs. The C, C++, and Rust memory models precisely define thread-safety as "the absence of data-races". Whatever the wikipedia says just does not apply (and if the wikipedia does not mention this, it is just incomplete in its treatment of thread safety).
- mratsim 6y agoHow does Rust prove that you are correctly using relaxed, acquire and release atomics?
- fluffything 6y agoIt doesn't. What Rust proves for safe Rust is that even if you were to use these incorrectly, your program is still data-race free and memory safe. That is, if you use relaxed where you actually wanted to use sequential consistency, your program might do many sorts of incorrect things (e.g. a counter is incremented in the wrong order), but it will not have undefined behavior (it won't dereference a null pointer, doing an access out of bound, double free, or having a data-race). To write atomic code that creates a data-race, you'd need to use unsafe Rust, and then your program would have UB. Rust proves this for safe Rust using ownership + borrowing, and `Sync`+`Send`. Ownership and borrowing deal with "aliasing xor mutability" which essentially eliminates all data-races, because a data-race requires a conflicting access involving two aliases where one is a write, and these two features prevent that from happening. `Sync` and `Send` provide proofs that some concurrent accesses are ok, e.g., an atomic relaxed write that conflicts with an atomic relaxed read is ok (what's not ok is unsynchronized conflicting accesses). As mentioned this does not proves that your program has no logic bugs, only that it has no data-races and UB. It is possible to write programs in safe Rust that do not do what you intend.
- mratsim 6y ago