As well as the tools I have listed above, there are many other OS structures to support better multitasking. For example:
- Fibers (sic, geddit?) are a Windows lightweight alternative to threads, which combine the pleasure of the Win32 threading interface with the intellectual opportunity afforded by the coroutine.
- Critical sections are Windows's lightweight alternative to mutexes, thus cleverly getting more use out of a previously well-defined phrase by using it to mean something related to but slightly different from the earlier general understanding.
- Not to be outdone by its closed source competition, Linux has sixteen types of mutex, varying the whole gamut of mutexity from lightweight to ultra-, hyper- lightweight.
- Lockless programming is a wonderful lightweight alternative to locky programming, which is great if it is applicable, which it rather often isn't. Most OSes offer special atomic increment and decrement operations to support this approach, and there is sometimes assistance in the programming languages too, which feeds into...
The old C language offered a pair of keywords with which one could season variable declarations:
register, which sounded rather staid, was an adjective essentially meaning 'fast'; whereas
volatile, which sounded exciting, was an adjective essentially meaning 'slow'. (Yes, yes; only
volatile is relevant here. I know.) Part of the expertise of the K&R generation was judicial decoration of one's code with these keywords. It often was only decoration. I discovered, by examining the output of my compiler. The damn thing took no notice at all. But at least the code looked good, which is the main thing.
register is gone, and
volatile is very old hat, being merely an unsuccessful technique to try to get the double checked locking pattern back on its feet. [pdf] So what is new?
Well, C++ is finally getting its own standard threading library. There. I am sure that Java people in particular are all mightily impressed by this, and are queuing all around the block to rejoin Bjarne's merry throng, like High Church C of E traditionalists flocking outside the local RC recruitment office.
More radically, the Intel people - who I suppose given their core enthusiasm are entitled to an opinion in these matters - believe that threads are far too hard for mere C++ programmers to manage. To this end, they have constructed the Threaded Building Blocks library, and released it under dual GPL and commercial licences. Here is a taster, cribbed from the pages of the accompanying O'Reilly book:
parallel_for(blocked_range(0, n, grainsize), avg);
This implements a parallel
for loop (duh!), with an iteration of the range
n-1 calling functor
avg. The work is automatically partitioned and handed out to the available processor cores, with each core dealing with at least
I thought this looked like a really easy-peasy approach to threading, and planned to make a parallel version of my latest project, which in one place iterates over an array of nearly 40 items. I was a bit taken aback when I found that the recommended first cut value of
grainsize was 10,000.
Walter Bright's D language takes an interesting approach to the problem of accidentally shared state. Instead of using a mechanism like C++'s
__declspec(thread) or Delphi's
threadvar to declare thread local storage - which, as Bright notes, hardly anybody uses - D defaults to all variables being allocated thread-local, and obliges the programmer to declare thread shared variables explicitly. Many other good things follow without much programmer effort - see here [pdf of talk slides] for details.
No round up such as this would be complete without mentioning the language du jour. Google's Go's goroutines are lightweight threads, often set to execute an inline lightweight lambda function and synchronise data via lightweight language-supported channels. It all looks jolly clever, and is so lightweight it might all be capable of being supported by hot air. Of course, I haven't actually tried it. I'm holding off until Google sees sense and implements full MI.