Erlang has a bunch of tools to help enforce determinism or at least suss out concurrency issues. For example: you can specify multiple receive statements to process your queued messages in a specific order, there is also a process manager (pman:start()) that allows you to explore concurrency related events, and not to mention Mutex Semaphores as a pattern to mitigate those issues.
There doesn't seem to be a real solution to deadlocks. I got the oreilly book in front of me and it's basically saying: be careful, but don't worry.
And I don't think erlang has a shared mutable states. In fact a google search for "erlang shared mutable state" has you as the first result.