No Silver Bullet
Over the course of three articles, we've looked at a number of approaches for writing code that scales to multicore and even clustered machines. For most code, this discussion is irrelevant. The set of programs that run fast enough on a single core grows every year, and individual core speeds continue to increase, albeit at a slower rate than 10 years ago.
When parallelism is important, it's often a significant benefit. Buying two CPUs costs a lot less than buying one CPU that's twice as fast, and has the advantage that you can always keep adding CPUs, while you can't always find faster ones. If your code is CPU-limited, making it parallel makes it easier to make it faster: Just throw more hardware at it.
None of the techniques that we've reviewed is the best solution to every problem. The correct approach to take depends on a lot of factors. Some concurrency models suit certain problems better than others. Irrespective of the problem, you're also likely to be constrained by existing code. For example, rewriting a large established codebase in Erlang isn't usually an option. Similarly, invasive modifications to make everything use transactional memory might not be a possibility.
If you're starting a new project from scratch, you have a lot more freedom. You can pick the right tool for the job that you're doing now, rather than the right tool for the job that someone was doing 10 years ago.