When discussing the problems of concurrency and parallelism, remarkably often someone pipes up with "You should just use Erlang!" This is frustrating.
I think by "Erlang" they mainly mean no-shared-memory, message passing processes. That is definitely a good way to structure many systems --- it avoids the pit of all evil, concurrency with unrestricted shared memory. But for many problems it is not a good fit. Many problems are fundamentally about concurrent updates to shared state, for example:
- Transfers between bank accounts
- Object interactions in a virtual world
- Scripts manipulating the DOM in a parallel browser
The right abstraction for these problems is atomic updates, a.k.a. transactions. In each transaction we want to read multiple values, do some computation, and update multiple values. We want the program behaviour to be as if transactions happen one at a time (atomicity), but we actually want updates to execute in parallel when they do not interfere.
This does not map well to pure message-passing systems in general. You can implement ad-hoc solutions to these transactional problems in most languages, including Erlang. You can even implement some sort of transactional memory in Erlang. But the language --- message passing in particular --- isn't helping you here. To cleanly express solutions to these problems we need a language (or if we're lucky, a library) which can directly describe shared state and atomicity, and implement them with some degree of parallelism.
Transactions are no panacea either! The point is just that message passing is often not the best way to express concurrency, and therefore the ideal system for parallel programming will contain more concurrency features than just message passing.