Message passing doesn't help either. What many programmers don't realize that synchronization problems (deadlocks) are _not_ the consequence of using mutexes or other primitives per se. They're the result of synchronization itself.
Message passing can be asynchronous, but on some level, the system might have to synchronize certain operations. If you implement a financial system, you'll certainly have to synchronize stuff even if you're using asychronous message passing to implement it -- you will simply implement synchronicity on the top of an asychronous infrastructure.
And when operations start to depend on each other, then you _have_ to think about potential deadlocks, race conditions, etc.
Basically there isn't anything that solves this for you. STM is somewhat different as the danger is not deadlocks but starvation, etc.
The way I like to put it is that using a decent concurrency mechanism like message passing or STM or even just what Go does (enforced by community standards rather than actual limitations) takes concurrent programming from an exponential-complexity problem to a polynomial-complexity problem. It's still hard, it'll never not be hard, but it doesn't have to be the insanely, mind-bendingly broken hard that it was in the 90s. The more you can avoid sharing and the more you can operate in your own little world that communicates with other worlds via immutable messages, the happier you will be, and if you occasionally have to dip a bit into true sharing, it's still easier to manage in a saner world than when you try to share everything, all the time.
There's nothing that "solves" the problem, but there are "things that will summon forth C'thulu" and "things that are merely difficult".
Message passing can be asynchronous, but on some level, the system might have to synchronize certain operations. If you implement a financial system, you'll certainly have to synchronize stuff even if you're using asychronous message passing to implement it -- you will simply implement synchronicity on the top of an asychronous infrastructure.
And when operations start to depend on each other, then you _have_ to think about potential deadlocks, race conditions, etc.
Basically there isn't anything that solves this for you. STM is somewhat different as the danger is not deadlocks but starvation, etc.