Ditch your mutex, you deserve better
Languages and STM Support
- Haskell is the main example of first-class STM, but commenters note varying levels of STM or similar in Clojure, Scala (ZIO, Cats Effect), Kotlin (Arrow), some C++ libraries, experimental Rust crates, Verse, and niche Go/C# libs.
- Several people stress that in many mainstream languages STM isn’t part of the core model and tends to be awkward or rarely used.
Mutexes vs STM vs Actors/CSP
- Core article claim repeated: mutexes “don’t compose” (especially across multiple resources), while STM composes transactions cleanly.
- Others argue composition problems are not unique to mutexes and that good designs (actors, message queues, single-writer threads, CSP) can avoid shared mutable state entirely.
- Counterpoint: actor/CSP approaches break down when you need atomic operations across multiple “owners” (e.g., account + some other resource); you’re back to explicit locking or transactional semantics.
Rust, C++, and Safer Mutex Patterns
- Rust’s
Mutex<T>pattern—tying data and lock together and using the borrow checker—gets praised for preventing unsynchronized access and some classes of bugs at compile time. - There’s a long sub‑thread about what a “mutex” really is, async vs sync locking, CPS transforms, and whether async patterns still conceptually constitute a mutex.
- C++ examples with
boost::synchronizedandstd::scoped_lockshow ways to compose locking over multiple objects and avoid classic deadlocks, though livelock/forward‑progress guarantees remain tricky.
Performance, Deadlocks, and OS/Hardware Considerations
- Some see mutexes as heavy, deadlock‑prone, and sensitive to OS behavior (e.g., .NET/Linux scheduling differences); others rebut that modern user‑space mutexes (e.g., futex/parking‑lot style) are lightweight and only syscall on contention.
- Discussion on cache-line contention, padding/alignment, spin vs sleep, and priority inversion shows that performance remains highly contextual.
- Hardware Transactional Memory (HTM) is mentioned as a partial accelerator for STM and multi‑word CAS, but Intel’s implementation is described as buggy/disabled and not a general solution.
Limits and Practical Problems of STM
- Several commenters emphasize long‑transaction issues: many small updates can starve a large transaction via repeated aborts; wound‑wait style schemes and MVCC/snapshotting are discussed as mitigations, but with tradeoffs.
- Databases’ transaction models are compared to STM; some note that common DB isolation levels already permit anomalies STM usually forbids.
- A number of people report that, in practice (especially in Clojure), STM feels slow, “colored,” and hard to reason about at scale; communities often fall back to atomics and queues instead.
Design, Semantics, and Concurrency Culture
- Clarifications appear on terminology: data race vs race condition in the C/C++/Rust memory model.
- Some see STM as promising but “owning” the architecture in the same way GC or async I/O do, making incremental adoption hard; C#’s abandoned STM effort is cited as a cautionary tale.
- General agreement: concurrent programming is intrinsically hard; the key is minimizing shared mutable state, carefully modeling contention, and recognizing there’s no silver bullet—whether mutexes, STM, actors, or channels.