Why does Rust have mutexes and other synchronization primitives, if mutable state sharing between tasks is not allowed?


My understanding is that it's not possible to share mutable state between tasks in Rust, so why does Rust has things like mutexes in the language? What's their purpose?

"Sharing mutable data between tasks is not allowed" is an oversimplification. No offense meant, it's also used in much introductory material on Rust, and for good reasons. But the truth is, Rust just wants to get rid of data races; not sharing anything is the preferred approach but not the only. Rust also wants to be a system programming language in the same sense as C and C++ are, so it won't nilly-willy completely remove some capability or performance optimization. However, in general shared mutable memory is not safe (data races etc.) so if you want it, you will have to acknowledge the responsibility by wrapping it in unsafe blocks.

Luckily, some patterns of using shared mutable memory are safe (e.g. using proper locking discipline). When these patterns are recognized and considered important enough, someone writes some unsafe code that they convince themselves (or perhaps even "prove") exposes a safe interface. In other words: Code using the interface can never violate the various safety requirements of Rust. For example, while Mutex allows you to access mutable memory from different tasks at different times, it never permits aliasing among tasks (i.e. access at the same time), so data races are prevented.