Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am interested in learning concurrent programming, focusing on the application/user level (not system programming). I am looking for a modern high level programming language that provides intuitive abstractions for writing concurrent applications. I want to focus on languages that increase productivity and hide the complexity of concurrent programming.

To give some examples, I don't consider a good option writing multithreaded code in C, C++, or Java because IMHO my productivity is reduced and their programming model is not intuitive. On the other hand, languages that increase productivity and offer more intuitive abstractions such as Python and the multiprocessing module, Erlang, Clojure, Scala, etc. would be good options.

What would you recommend based on your experience and why?

EDIT: Thanks everybody for your interesting answers. It's hard to make a conclusion without actually trying since there are many good candidates: Erlang, Clojure, Scala, Groovy, and perhaps Haskell. I voted the answer with the most convincing arguments, but I'll try all the good candidates before deciding which one to pick :)

share|improve this question

closed as off-topic by Thomas Owens Oct 24 at 14:07

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about what language, technology, or project one should take up next are off topic on Programmers, as they can only attract subjective opinions for answers. There are too many individual factors behind the question to create answers that will have lasting value. You may be able to get help in The Whiteboard, our chat room." – Thomas Owens
If this question can be reworded to fit the rules in the help center, please edit the question.

21  
To give an example, I don't consider a good option writing multithreaded code in C, C++, or Java. Why? On the other hand, Python and the multiprocessing module, Erlang, Clojure, Scala, etc. are some of my options. Again, why? Expand your question to better define what you're actually looking for. –  Yannis Rizos Nov 22 '11 at 18:17
2  
So do you want to learn parallel programming with all the gotchas or you want to hide some of its complexity and focus on productivity? –  MaR Nov 22 '11 at 18:24
1  
@DeadMG Decreased productivity is their problem. I don't want to focus on the syntax of the language instead of the problem. I definitely don't want to end up struggling with deadlocks. As a simple example, I want to use simple statements such as begin transaction end transaction and everything inside should be deadlock-free and either succeed or fail as a whole. –  faif Nov 23 '11 at 18:43

16 Answers 16

up vote 31 down vote accepted

You almost certainly should look at Clojure - in my opinion it's the best modern language for multi-core programming and it is extremely productive.

Key attributes:

  • It's a functional language, which is a boon for both concurrency and your ability to develop using higher level abstractions. It features fully immutable persistent data structures and lazy sequences which will be familiar to anyone with experience in functional languages like Haskell.
  • It features a very novel software transactional memory system for concurrent lock-free access to mutable state. Making code concurrency-safe is often as simple as wrapping it in a (dosync....) block.
  • It's a Lisp - which makes it extremely powerful for macro-based metaprgamming and code generation. This can bring significant productivity advantages (essay by Paul Graham - "Beating The Averages")
  • It's a JVM language - so not only do you get access to the huge array of libraries and tools in the Java ecosystem, you also benefit from the huge engineering effort that has gone into making the JVM an effective platform for concurrent server-side applications. For practical purposes, this gives it a huge advantage over languages that don't have this kind of foundation to build upon.
  • It's dynamic - which results in very concise code and a lot of productivity. Note however that you can use optional static type hints for performance if needed.
  • The language is designed around abstractions which is somewhat hard to explain but the net effect is that you get a set of relatively orthogonal features that you can combine to solve your problems. An example would be the sequence abstraction, which enables you to write code that deals with every "sequential" type of object (which includes everything from lists, strings, Java arrays, infinite lazy sequences, lines being read from a file etc.)
  • There's a great community - helpful, insightful but most importantly very pragmatic - the focus in Clojure is generally on "getting things done".

Some mini code samples with a concurrency slant:

;; define and lanuch a future to execute do-something in another thread
(def a (future (do-something)))

;; wait for the future to finish and print its return value
(println @a)

;; call two functions protected in a single STM transaction
(dosync
  (function-one)
  (function-two))

In particular, it's worth watching one or more of these videos:

share|improve this answer
12  
The purpose of static type declarations in strongly-typed languages is not to "improve performance where needed," and I'm getting kind of sick of Lisp advocates trotting out that old strawman. Type declarations have two purposes: to provide certain compile-time guarantees of correctness, and to make the code easier to read, especially for someone other than the original author. The inherently better performance that static typing provides is just a bonus. –  Mason Wheeler Nov 23 '11 at 17:44
5  
I've had to work with another developer's JavaScript code lately at work, and that's the most painful part of the process: with no types on the function arguments, I have to hunt throughout the entire codebase to figure out what they're supposed to be and what they can do based on where they're called from. This would be a non-issue if JavaScript had retained C's type system in addition to its general syntax. –  Mason Wheeler Nov 23 '11 at 17:45
1  
@MasonWheeler: IMHO if you can't figure out how to call a function without type annotations, it's a problem with the documentation (or lack thereof). Even in duck typed languages everything usually has to satisfy some structural type constraints (e.g. must support arithmetic operations, must be iterable, must be indexable, etc.). Static types would only help minimally because they wouldn't give much hint about what the function does. –  dsimcha Nov 24 '11 at 0:50
1  
@Mason I never said that there weren't other advantages to static type declarations. In fact I like static type declarations for exactly the reasons you state. However I also like the productivity gains of dynamic typing. It's a trade-off. If you have a good test suite, I generally find that this mitigates a lot of the downsides of dynamic typing both in terms of ensuring correctness and providing example code to help newcomers understand correct usage. YMMV. –  mikera Nov 25 '11 at 11:40
1  
@dsimcha - the alternative to designing around abstractions would be to design around a concrete implementation. For example, most of the old Lisp functions worked only on linked lists stored in cons cells. You needed different functions for different data structures. In Clojure, the core library function work on anything sequential (as in the answer). –  mikera Nov 25 '11 at 11:43

Take a look at Microsoft's Parallel Programming for .net. It is very intuitive.

Many personal computers and workstations have two or four cores (that is, CPUs) that enable multiple threads to be executed simultaneously. Computers in the near future are expected to have significantly more cores. To take advantage of the hardware of today and tomorrow, you can parallelize your code to distribute work across multiple processors. In the past, parallelization required low-level manipulation of threads and locks. Visual Studio 2010 and the .NET Framework 4 enhance support for parallel programming by providing a new runtime, new class library types, and new diagnostic tools. These features simplify parallel development so that you can write efficient, fine-grained, and scalable parallel code in a natural idiom without having to work directly with threads or the thread pool. The following illustration provides a high-level overview of the parallel programming architecture in the .NET Framework 4... http://i.msdn.microsoft.com/dynimg/IC292903.png

share|improve this answer

Both Erlang and Scala have actor-based concurrency, which I found very intuitive and easy to learn.

The Actor model in computer science is a mathematical model of concurrent computation that treats "actors" as the universal primitives of concurrent digital computation: in response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and determine how to respond to the next message received... It has been used both as a framework for a theoretical understanding of computation, and as the theoretical basis for several practical implementations of concurrent systems.

share|improve this answer

I think it depends on what it is you're building. Desktop apps, or server? I've heard that (but don't have personal experience) node.js great for concurrent programming for servers (both in terms of writing code and in performance). If I wanted to write a new server app, I'd probably try that out. Not sure about desktop apps... I've written a fair amount of stuff in C# and there are some tools that hide the complexity nicely, though for other cases you have to deal with it head-on.

share|improve this answer

Erlang is definitely a great option, but something a little more practical might be Go, Google's new language.

It's not so far from other common languages, so it's typically easy to get if you already know other 'easy' languages. Many people compare it with Python or even Lua in terms of how 'comfortable' is it to program.

share|improve this answer
1  
@Chiron: Erlang is a programming language, it's used to create applications. Typically, multitprocessing applications. I don't know where does it fit as 'systems concurrent proramming', I haven't heard of any OS written in Erlang. –  Javier Nov 23 '11 at 13:56
1  
After taking a quick look in the Go tutorial I want to say that IMHO a language with a C-like syntax which uses (limited) pointers is definitely not a modern language that increases productivity. –  faif Nov 23 '11 at 18:40

In the next version, C# makes it even easier than that diagram shows. There are two new keywords Async and Await.

Async is used as a function modifier and says "this operation performs its work on another thread.

Await is used within an Async function, and this is where the magic happens. Basically Await tells the compiler to run the operation following the keyword in a seperate thread and wait for the results. Any code after the await call runs after the operation.

ALSO, the operation synchronizes to the calling thread (so if you are doing an asynch operation in response to a button click, you don't have to manually post back to the UI thread). Two little keywords and you get a lot of concurrency power. Read more here

share|improve this answer

You may also want to look at Groovy and the GPars library. GPars BTW is somewhat similar to .NET Parallel Extension mentioned in another answer, but Groovys flexible syntax makes it read better in some circumstances.

share|improve this answer

You could try D. It offers three models. I recommend either the first or second.

  1. std.concurrency. If you use this module for all your concurrency needs, then a combination of the language and the standard library enforces isolation between threads. Threads primarily communicate via message passing, with limited support for shared memory in a way that favors "safety first" and disallows low-level data races. Unfortunately the documentation of std.concurrency needs improvement, but the model is documented in a free chapter of Andrei Alexandrescu's book, "The D Programming Language".

  2. std.parallelism. This module is designed specifically for multicore parallelism rather than general-case concurrency. (Concurrency and parallelism are not the same thing, though concurrency is necessary to implement parallelism.) Since the whole point of parallelism is performance, std.parallelism doesn't make any isolation guarantees because they would make writing efficient parallel code difficult. However, it does abstract away a lot of error-prone low-level details so that it's very hard to screw up if you're parallelizing workloads that you've manually verified are mutually independent.

  3. core.thread is a low-level wrapper over OS-specific threading APIs. Both std.concurrency and std.parallelism use it under the hood, but I would only recommend using it if you're writing your own concurrency library or find some ridiculous corner case that can't be done well in either std.parallelism or std.concurrency. No one should use something this low-level for day-to-day work.

share|improve this answer

What about Clojure? You can use Swing for example but enjoying Clojure concurrent programming facility? Clojure has a pretty well Java integration.

Also, have you considered Java 7 Fork/Join framework?

share|improve this answer

I'm learning about Haskell right now, and reading this paper has convinced me that Haskell is a good option for concurrent programming. Because it's purely functional (the type system knows whether a function does any input, output, or reading/modification of global state), it can do things like Software Transactional Memory (summed up very nicely in the above paper) which behaves similarly to transactions in databases - you get a bunch of nice things like atomicity with only a little extra sugar. AFAIK, Haskell threads are very light-weight too. In addition to these things, the fact that Haskell is purely functional lets even simple tasks be run in parallel with little more than a single keyword (par). source

share|improve this answer

I'd still recommend C++. It is more than capable of the necessary abstractions to write decent concurrent code. The overwhelming probability is that you simply have a poor library for doing the job, since good libraries for doing the job are relatively new, and indeed, the knowledge for using C++ well is not exactly common. Intel's TBB has only been around for a few years, and Microsoft's PPL has only shipped since last year.

If you use something like TBB or PPL, then concurrent code is, well, not exactly trivial to write, insofar that concurrency is never trivial, but far from arduous. If you use pthreads or Win32 threads directly, then it's no wonder you don't like it- you're practically writing in assembler with such functions. But with the PPL, then you're talking about standard functional algorithms that are parallelised for you, generic data structures for concurrent access, and that sort of good stuff.

share|improve this answer
1  
Check out Boost.Threads or C++0x std::thread (or std::tr1::thread). It's actually a very good abstraction, IMO. –  greyfade Nov 23 '11 at 17:31
1  
@greyfade: They have absolutely nothing on PPL or TBB. boost::thread is just an OS wrapper with a little RAII. PPL and TBB are real concurrent algorithms, containers, etc. –  DeadMG Nov 25 '11 at 11:04

I would suggest Groovy/Java/GPars if you can be JVM based since it allows for actors, dataflow, communicating sequential processes (CSP), data parallelism, software transactional memory (STM), agents, ... The point here is that there are many high-level concurrency and parallelism models each of which has different "sweet spots". You do not want to use a model that is not in harmony with the solution to a problem you are trying to construct. Languages and frameworks with only one model coerce you into algorithm hacking.

Of course I might be seen as biased as I am contributor to Groovy and GPars. On the other hand I do work with CSP and Python, cf. Python-CSP.

A further point is that the original question is about learning, not about writing a production system. So the Groovy/Java/GPars combination is a good way of learning even if the eventual production work is done in C++ using something like Just::Thread Pro or TBB rather than being JVM based.

(Some perfectly reasonable URL links had to be removed because of some panic about spamming by the host site.)

share|improve this answer

Google's GO language has some interesting tools for concurrency - that would be another fun thing to try. See: http://golang.org/doc/effective_go.html#concurrency and read down a bit for examples.

Concurrent programming is a large topic and there is space only for some Go-specific highlights here.

Concurrent programming in many environments is made difficult by the subtleties required to implement correct access to shared variables. Go encourages a different approach in which shared values are passed around on channels and, in fact, never actively shared by separate threads of execution. Only one goroutine has access to the value at any given time. Data races cannot occur, by design. To encourage this way of thinking we have reduced it to a slogan:

Do not communicate by sharing memory; instead, share memory by communicating.

This approach can be taken too far. Reference counts may be best done by putting a mutex around an integer variable, for instance. But as a high-level approach, using channels to control access makes it easier to write clear, correct programs.

One way to think about this model is to consider a typical single-threaded program running on one CPU. It has no need for synchronization primitives. Now run another such instance; it too needs no synchronization. Now let those two communicate; if the communication is the synchronizer, there's still no need for other synchronization. Unix pipelines, for example, fit this model perfectly. Although Go's approach to concurrency originates in Hoare's Communicating Sequential Processes (CSP), it can also be seen as a type-safe generalization of Unix pipes...

share|improve this answer

A plug for Ada is needed here, as it has all the top level abstractions for parallelism & concurrency. otherwise known as tasking. Also as OP asked for intuitive (a subjective criteria!) i think a different approach to the java-centric world might be appreciated.

share|improve this answer

I may get hit over the head for this, but have you read chapter 7 of TAOUP? The section I'm thinking of specifically is threads vs processes. I've found that the concept of concurrent processing makes most people think of threads, yet I've never seen an instance where a thread is easier and faster to use than spawning a child process.

You are farming out all the details of handling concurrency to the smart guys who built your OS. There's already lots of communication methods in place, and you don't have to worry about locking of shared resources. Basically, threads are an efficiency hack, which falls under the rule of optimization. Don't optimize if you haven't tested for necessity.

Find a good subprocess library, such as envoy for python. Or you could just write several separate programs in C, and write another "master" program to use fork and pipe to spawn and communicate with the subprocesses.

share|improve this answer
3  
This is the opposite of what OP explicitly wants … spawning a process is just as low-level as spawning a thread manually. OP is interested in high-level abstractions of concurrency. –  Konrad Rudolph Mar 12 '12 at 18:33

Scala has been mentioned several times in the questions and in answers, but I have seen no reference to Akka which is an actor implementation that can be used with both Scala and Java.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.