[HN Gopher] Shared mutable state in Rust (2022)
___________________________________________________________________
Shared mutable state in Rust (2022)
Author : vinhnx
Score : 39 points
Date : 2026-04-01 23:33 UTC (3 days ago)
(HTM) web link (draft.ryhl.io)
(TXT) w3m dump (draft.ryhl.io)
| FpUser wrote:
| I have shared mutable state which is available through the whole
| application lifetime. Having ARC in this situation makes no
| sense, single mutex should be all I need.
| LtdJorge wrote:
| Use a LazyLock for your state, then
| kd5bjo wrote:
| That's also an option available to you: Mutex::new() is const,
| so there's no trouble putting one in a static variable. If the
| inner value can't be const-constructed, you'll need a way to
| prevent access before it's initialized; for that, you can use a
| OnceLock or just Box::leak() the Mutex once it's constructed
| and pass around a simple reference.
| Ciantic wrote:
| I happen to be just now experimenting with app states. Out of
| interest, you mean something like this? https://gist.github.c
| om/Ciantic/63526ebfe65570b669eca33bf340...
|
| What would be disadvanatages of this approach? I don't like
| Arc's myself either, I would like to see what is best
| alternative for those in multi threaded apps.
| maxbond wrote:
| Different commenter but yes, that's exactly what they mean.
|
| The main disadvantage is strong coupling. The shared state
| inside the static makes it more difficult to test your
| code. There are ways to reduce this coupling, the most
| obvious being that you push as much logic as possible into
| functions that accept a reference rather than use your
| static directly. Then you minimize the size of the code
| which is difficult to test, and cover it with end to end
| testing.
|
| The OnceLock does impose 1 atomic operation of overhead,
| whereas an Arc imposes 2 (in this case, it can be more if
| weak references are used). However neither are likely to be
| important when you consider the overhead of the Mutex; the
| Mutex is likely to involve system calls and so will
| dominate the overhead. (If there's little to no contention
| then the Mutex is a lot like an Arc.)
|
| Your alternative would be to use `Box::leak()` as the
| parent comment describes, which would force you to pass a
| reference around (resulting in better coupling) and
| eliminate overhead from OnceLock. However, it's unlikely to
| result in any material performance benefit, and you could
| reduce coupling without departing from your current
| approach, so I don't think either approach is clearly or
| overwhelmingly better.
| mplanchard wrote:
| You can Box::leak() it to make a &'static ref to it.
| the__alchemist wrote:
| I think which tools you use for concurrency depends on your code
| style and what you're doing. For example, I haven't reached for
| Arc in a while. Example of the two primary ways I've been doing
| it:
|
| Embedded: Mutex + critical sections + hardware interrupts. The
| Mutex isn't std::Mutex, but a hardware-specific one. (E.g. ARM)
| works in a similar way. The default syntax is a mess of RefCell,
| Cell, Option, with the requisite < and > characters. (The Option
| is so you can insert a value in on init, then it's never None)
| etc. I work around this with macros.
|
| PC applications (GUI, 3D etc): std::thread and MPSC
| receivers/transmitters which update a state struct when they're
| ready. Then poll in the GUI's event loop or w/e. I believe this
| workflow has worked for me in lieu of Arc because I have been
| structuring programs with a single main thread, then sub threads
| which perform non-blocking tasks, then return data to the main
| thread.
|
| Also: If it's a primitive type, Atomics are nice.
___________________________________________________________________
(page generated 2026-04-05 23:01 UTC)