Please help continue this discussion by sharing your thoughts in the comments below.

Which 2-3 languages/approaches should a programmer be studying to move toward a more concurrent future?

Tony Well, besides Reia... :)

1) Erlang: Obviously I believe in the actor model quite a bit, which is the basis of Erlang's approach to concurrency. You can diagram a concurrent system on a whiteboard in terms of different components which talk to each other with messages, and pretty much translate that diagram directly into code. Concurrency is localized to actors, which makes it a lot easier to reason about. The Erlang VM has some issues with scalability on massively multicore systems now but they're being resolved, and the Erlang model makes optimizing concurrency in the VM incredibly easy. All that said, far and away the thing that makes Erlang so incredibly cool is the nearly seamless distribution across multiple systems, which is something Erlang can do far better than any other language in existance. Also, Erlang makes handling faults in concurrent systems comparatively easy, and when it comes to concurrent systems simplified fault handling is invaluable.

2) Haskell: In some regards Haskell is farther along than Erlang when it comes to concurrency, and provides multiple different models for different types of concurrency, whereas Erlang pretty much forces you to use one (the actor model/shared nothing concurrency). However, I prefer Erlang to Haskell as I'm not a fan of pure functional programming/monads and think Erlang's dirty imperative features like its approach to I/O actually make writing programs simpler and more practical. All that said, at Erlang Factory Ulf Wiger pointed out how horribly Erlang performs on shared state concurrency problems like chameneos-redux, which Haskell does great on. I appreciate Haskell providing multiple approaches to modeling concurrency in the same environment.

3) Clojure: uses Software Transactional Memory (STM) for modeling concurrency, which has been around in other places (like Haskell) before but Clojure does some neat stuff as far as simple Lispy syntax for marking sections of the code atomic and also permitting mutable state within the atomic sections. This is great for shared state concurrency problems, but most concurrent problems don't require shared state, and I think reasoning about STM systems is more difficult than actor-based systems because there's no logical mapping between what the system is doing concurrently and how the code is structured. It's sort of like throwing a bunch of queries at a database, and when things start going unexpectedly slow, or break, you're kind of left to wonder what's going on.

Venkat Studying a language is not about learning the syntax, but to learn the idioms and beginning to think along the lines of designing applications using those. From a practical point of view, I don't think you — a busy everyday programmer — have the time and energy to study multiple languages at the same time. So, I don't recommend studying 2 to 3 languages.

At any given time, as a professional programmer you should be studying a language.

One one hand, the language you pick must be quite different from the one you are using extensively. In addition to exercising your mental muscle, it helps you not get boxed into the paradigms and idioms promoted by one particular language you're used to.

On the other hand, if you intend to put some of the studying to real use relatively soon, it will help for that language you learn to integrate well with the language or the platform you're working with. However, if you learn continuously, you'll find it easier and quicker to pick the language with features you desire and integrates well with your current platform or language. So, focus on one language at a time.

From the point of view of concurrency, rather than learning a language specifically, I suggest learning the different approaches. Rather than assuming a particular approach is the right one (or the wrong one), learn the pros and cons of each. Understand what problem they solve, where they would be useful, and what their limitations are. Don't restrict your learning to the approaches supported by one language, your favorite language, or what's currently creating the buzz. Sometimes what's old becomes new again. Learn about the shared state vs. message passing, Communicating Sequential Processes, the Actor based model, Nested Data Parallelism, Software Transactional Memory,...

MenTaLguY Erlang and Haskell, but I'd like to offer a different sort of justification from those which are usually offered. The thing is, both of these languages sort of force you to take the functional programming beast by the horns. It isn't actually hard, but it requires learning new habits — and those habits actually happen to correspond nicely to the habits required for writing good concurrent programs (at a high level — low-level optimizations are another story).

It does also happen that they each more or less represent the two main modes of concurrent programming — message-passing (as represented by actors in Erlang) versus shared-memory (as represented by STM in Haskell), so you'll get a flavor for each that way. But do realize that there are lots of different ways of looking at message-passing besides just actors; joins as in JoCaml, for instance.

Also, in general, I think the main goal for learning new programming languages should be to stretch your brain and find things to take back to your work in your usual languages. (No matter how different it is from what you're used to — and it should be different if you intend to stretch your brain — there will always be something.) You may find a language you end up falling in love with in the process (Ruby was one such language for me), but it's better not to approach new languages with such high expectations.