When you pass data to another thread, there are three options: 1) pass a copy, 2) hand off ownership to the other thread, and 3) transfer ownership to a mutex object, then borrow it from the mutex object as needed. All of these are memory and race condition safe due to compile time checking.
Those are the concepts. The Rust syntax needed to support it is somewhat complicated, but if you get it wrong, you get compile time error messages.
This may be the biggest advance in software concurrency management since Dijkstra's P and V. Almost everything in wide use is either P and V under a different name, or some subset of P and V functionality. Locks are not a basic part of most languages; the language doesn't know what a lock is locking. The Ada rendezvous and Java synchronized objects are exceptions. Those were good ideas, but too restrictive. Finally, we're past that.
Go could have worked this way. Go originally claimed to be concurrency safe, but it's not. You can pass a reference across a channel, and now you're sharing an unlocked data object. This is easy to do by accident, because slices are references. Because Go is garbage collected, it's almost memory safe (there's a race condition around slice descriptors that can be exploited), but it doesn't protect the program's data against shared access. In Rust, when you pass an non-copyable object across a channel, the sender gives up the right to use it, and the compiler enforces that.
[1] http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.ht...