3 ms·
Most of this internal bookkeeping is at compile time, right? Your average object that contains a bunch of mutable fields will, even in Rust, be expressed using
by geofft 5y ago
Most of this internal bookkeeping is at compile time, right?
Your average object that contains a bunch of mutable fields will, even in Rust, be expressed using a mutex. For instance, here's a very simple race-free program that transfers $20 to Alice from Bob and $30 from Bob to Alice: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c6f47a6102afaf31a90b21e28cd43df4 https://play.rust-lang.org/?version=stable&mode=debug&editio... It uses
struct Bank {
alice_balance: i32,
bob_balance: i32,
}
and keeps the bank inside a Mutex (or more specifically inside an Arc<Mutex<Bank>> to manage ownership across threads). This is a pretty straightforward pattern based on the Mutex docs: https://doc.rust-lang.org/std/sync/struct.Mutex.html https://doc.rust-lang.org/std/sync/struct.Mutex.html
In this case, the individual threads that perform the transfer are not applying any additional overhead to alice_balance or bob_balance. Those are regular old int32_t variables in a regular old struct, same as C/C++. The only thing that's being prevented is that the compiler won't let me write a version of this program that doesn't have the Mutex. There's a lot of analysis going on inside the compiler to confirm this, but once the compiler is happy, there's no runtime overhead compared to the equivalent C/C++ program.
(So I don't think "you don't have to think of it" is really what's going on. You have to think of it. It's just that if you don't, your program won't compile.)
Now, you can write a version of the program that uses thread-safe data types for the balances directly, maybe something like this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9088c70ebfcae584de87bf38caa97b4d https://play.rust-lang.org/?version=stable&mode=debug&editio...
struct Bank {
alice_balance: AtomicI32,
bob_balance: AtomicI32,
}
And it is true that there is now extra overhead in this version of the program, and the "advantage" is you could get rid of the mutex and it would still compile. But why would you write it this way? You know that you want the accesses to be transactional. You know you're going to want a mutex (or something) around the Bank. Why add the atomic types?
If Rust somehow used atomic integers by default (or something like a global interpreter lock) so you didn't have to think about it and code compiled whether or not you locked things properly, then yes, I'd agree. But it doesn't - it uses normal integers and things fail to compile.