Just on your last point, Rust does have the ability to do unsafe code (and many multi-threading primitives use these internally). The real question is, how can these be exposed to Rust in a way that plays nicely with other Rust code.
There are things like RefCell, which enables multiple threads to hold a reference to an object, with run-time checking of borrows. Or there are also explicit mutex wrappers that can be used. You could use these with channels, closures, or a callback system.
As Rust matures, we should see more of these kinds of features find themselves into the standard library.
The real question is, how can these be exposed to Rust in a way that plays nicely with other Rust code.
Yes, that's exactly the question I'm asking myself. I know that you can do everything in unsafe, but as soon as I step into that mode I'm getting the feeling that it might end up in the same level as C++ or probably even more complicated.
It probably shouldn't have to do with dealing explicitly with mutexes. If you have to I think that things like std::sync::Mutex are no good solutions because they are not really general purpose. If you really deal with low-level multithreading problems you often have multiple mutexes that might need to be locked in a special order and the mutexes are normally part of a data structure and do not own the data.
But multithreading is only a part of the whole problem. The other one is achieving easy-to-use and safe concurrency in a single thread (like Javascript APIs).
There are things like RefCell, which enables multiple threads to hold a reference to an object, with run-time checking of borrows.
RefCells do not allow multiple threads to hold a reference to an object because they are not Sync. They only permit dynamic enforcement of Rust's borrowing rules for references, through "interior mutability", as you said.
There are things like RefCell, which enables multiple threads to hold a reference to an object, with run-time checking of borrows. Or there are also explicit mutex wrappers that can be used. You could use these with channels, closures, or a callback system.
As Rust matures, we should see more of these kinds of features find themselves into the standard library.