In conventional blocking languages, you can get a start on parallelizing your programs this way:
- break program into function calls that match the steps that can happen in parallel
- wrap the function calls in messages passed over the network
+ i.e. process(thing) -> post(thing)/poll_for_things()
- split the sender and receiver into different processes
OF COURSE there are big advantages to using a language (Erlang) or a heavyweight framework (map/reduce) designed for concurrency. Rolling your own process-centric concurrency is a different set of tradeoffs, not a panacea. But it's worth considering for some problems.