logoalt Hacker News

globalnodeyesterday at 10:58 PM5 repliesview on HN

so does the rust compiler check for race conditions between threads at compile time? if so then i can see the allure of rust over c, some of those sync issues are devilish. and what about situations where you might have two variables closely related that need to be locked as a pair whenever accessed.


Replies

tczMUFlmoNkyesterday at 11:14 PM

> what about situations where you might have two variables closely related that need to be locked as a pair whenever accessed.

This fits quite naturally in Rust. You can let your mutex own the pair: locking a `Mutex<(u32, u32)>` gives you a guard that lets you access both elements of the pair. Very often this will be a named `Mutex<MyStruct>` instead, but a tuple works just as well.

andsoitistoday at 12:02 AM

> so does the rust compiler check for race conditions between threads at compile time?

My understanding is that Rust prevents data races, but not all race conditions. You can still get a logical race where operations interleave in unexpected ways. Rust can’t detect that, because it’s not a memory-safety issue.

So you can still get deadlocks, starvation, lost wakeups, ordering bugs, etc., but Rust gives you:

- No data races

- No unsynchronized aliasing of mutable data

- Thread safety enforced through type system (Send/Sync)

show 1 reply
treydtoday at 12:13 AM

This was a primary design goal for Rust! To prevent data races (and UAF and other types of memory unsafety) by construction through the type system.

PartiallyTypedyesterday at 11:24 PM

In rust, there are two kinds of references, exclusive (&mut) and shared(&). Rustc guarantees you that if you provide an exclusive reference, no other thread will have that. If your thread has an exclusive reference, then it can mutate the contents of the memory. Rustc also guarantees that you won't end up with a dropped reference inside of your threads, so you will always have allocated memory.

Because rust guarantees you won't have multiple exclusive (and thus mutable refs), you won't have a specific class of race conditions.

Sometimes however, these programs are very strict, and you need to relax these guarantees. To handle those cases, there are structures that can give you the same shared/exclusive references and borrowing rules (ie single exclusive, many shared refs) but at runtime. Meaning that you have an object, which you can reference (borrow) in multiple locations, however, if you have an active shared reference, you can't get an exclusive reference as the program will (by design) panic, and if you have an active exclusive reference, you can't get any more references.

This however isn't sufficient for multithreaded applications. That is sufficient when you have lots of pieces of memory referencing the same object in a single thread. For multi-threaded programs, we have RwLocks.

https://doc.rust-lang.org/std/cell/index.html

ViewTrick1002yesterday at 11:06 PM

It entirely prevents race conditions due to the borrow checker and safe constructs like Mutexes.

Logical race conditions and deadlocks can still happen.

show 2 replies