Concurrency: So Easy it’s Hard

There’s a seemingly perpetual undercurrent of buzz in the software world about simplifying concurrency (aka multithreading, parallelism, etc…). 

Since software makers are in the business of making software many of these solutions focus on simplifying the software involved in the implementation of concurrency.  For example, the next version of the .NET Framework, .net 4.0, adds parallel extensions.  Old mainstays such as PVM and MPI are extensions to C designed to simplify concurrency.  Java shipped with its own threading API.  There are many others that can be added to this list (e.g., Stackless Python).

I’d say that the problem of creating concurrency, that is, creating a system that depends on multiple sequences of instructions executing simultaneously, has been solved so well that it’s been solved too well.  It’s so easy to create concurrency that we can do it without realizing it (e.g., event driven programming).

Meanwhile, the difficulties associated with concurrency do not typically stem from lack of library (or syntax) support.  Concurrency is hard because it’s hard to model/design in way that is both correct and maintainable.

This is not, per se, a problem of software libraries or syntax.  It’s a problem of comprehension and communicating comprehension.  The difficulty of modeling concurrent processes is to be expected given that our most basic modeling tool , the human brain, is not very good at executing multiple complex tasks simultaneously.  Sequential thinking, for complex tasks, is so rooted in our psychology that it can be used to our advantage: if you don’t want to be distracted by random thoughts then focus on a single thought because “you can only focus on a single thing at a time”.

The solution, in my opinion, is to do what we always do when the number of mental widgets necessary to successfully handle a task exceeds the ability of most individual brains; come up with concurrency focused abstractions that gloss over as much non-concurrency related detail as possible while remaining useful.

In this case, since the problem is design and communication of design, the focus should be on improved notation.  We need notation that makes shared state leap off the page.  Notation that makes it clear when our designs may result in deadlocks.  Notation that calls attention to results that depend on the order in which multiple threads of execution complete (race conditions).  Perhaps most importantly we need notation that is widely used so that the complex orchestration of instruction streams we call concurrency can not only be created but modified, adapted, extended, etc… as well.

No comments:

Post a Comment