The future of concurrent programming
Sean Kelly
sean at f4.ca
Tue May 29 11:19:40 PDT 2007
Regan Heath wrote:
> Daniel Keep Wrote:
>>>
>> We can; it's just hard as hell and thoroughly unenjoyable. Like I said
>> before: I can and have written multithreaded code, but it's so utterly
>> painful that I avoid it wherever possible.
>
> I must be strange then because after 5+ years of multithreaded programming it's the sort I prefer to do. Each to their own I guess.
Same here. That said, I still believe this is something the user
shouldn't generally have to think about. Let's say you want to sort a
large array. Is it better to do so using a single thread or multiple
threads? What if the app must adapt to use whatever resources are
available, be that 1 CPU or 16 CPUs? We are quickly heading towards an
area where few competent multithreaded programmers even have experience.
It's not terribly difficult to target 2-4 CPUs because the number is
sufficiently small that multi-threaded programs still look much like
single-threaded programs. But what if the target machine has 16 CPUs?
32? The more parallel machines get the worse explicit multi-threading
fits. Eventually, I will want the compiler/VM to figure most of it out
for me, or at least let me explicitly designate functions as atomic,
etc. Cilk is a decent example of how a C-like language could be adapted
for multi-threading, but I still consider it an example of yesterday's
solution, not tomorrow's.
> now, I haven't tested the above in D but in Java and C# the 'lock' statement causes a deadlock above because you cannot lock the same object twice, even from the same thread.
Locks are recursive in D (thank goodness). But that only solves on eof
the two problems you mention.
> In my previous job we used a mutex object that allowed the same thread to lock the same object any number of times, counting the number of lock calls and requiring an equal number of unlock calls. This idea makes life a lot easier. No more deadlocks of this type.
Yup, this is how D works.
> That just leaves the deadlock you get when you say:
>
> synchronize(a) { synchronize(b) { .. } }
>
> and in another thread:
>
> synchronize(b) { synchronize(a) { .. } }
>
> Given the right (or rather wrong) timing this can result in a dealock of both threads. This situation is less common simply because it's less common for 2 blocks of code in 2 different threads to need 2 or more mutexes _at the same time_. Or, at least, that is my experience.
This is why some people (like Herb Sutter) say that object-oriented
programming is inherently incompatible with explicit multi-threading.
Any call into unknown code risks deadlock, and the whole point of OOP is
generalizing problems in a manner that requires calling into unknown
code. It's no wonder that message passing (as with CSP) seems to be
gaining traction.
> I wonder what D's synchronized statement does? Does it allow multiple locks from the same thread? It should, especially given that it is impossible to forget the unlock call (that in itself is a great boon to multithreaded development).
Yes it does.
> Another good idea is to provide a ThreadPool construct, do we have one of those floating around (pun intended). The idea being that when you need a thread you ask the pool for one and it supplies it, then once you're done with it you release it back into the pool for the next piece of code to pick it up and run with it (get it, run with it, like a ball... well I thought it was funny).
Tango will almost certainly have one prior to its 1.0 release. It
already has a ThreadGroup object, but this is more for simply grouping
multiple threads than it is for providing a general means for performing
async. tasks. I'm not yet sure just how extensive multi-threading
support will be added to Tango by 1.0, but definitely more than it has now.
Sean
More information about the Digitalmars-d
mailing list