Hi Bruce,
Some comments from an 11 year Java professional and occasional Haskell
hobbyist.
On 9 Sep 2008, at 20:30, Bruce Eckel wrote:
So this is the kind of problem I keep running into. There will seem
to be consensus that you can do everything with isolated processes
message passing (and note here that I include Actors in this
scenario even if their mechanism is more complex). And then someone
will pipe up and say "well, of course, you have to have threads" and
the argument is usually "for efficiency."
One important distinction to make, which can make a lot of difference
in performance, is that shared memory itself is not a problem. It's
when multiple threads/processes can update a single shared area that
you get into trouble. A single updating thread is OK as long as other
threads don't depend on instant propagation of the update or on an
update being visible to all other threads at the exact same time.
I make two observations here which I'd like comments on:
1) What good is more efficiency if the majority of programmers can
never get it right? My position: if a programmer has to explicitly
synchronize anywhere in the program, they'll get it wrong. This of
course is a point of contention; I've met a number of people who say
"well, I know you don't believe it, but *I* can write successful
threaded programs." I used to think that, too. But now I think it's
just a learning phase, and you aren't a reliable thread programmer
until you say "it's impossible to get right" (yes, a conundrum).
In general I agree. I'm (in all modesty) the best multi-thread
programmer I've ever met, and even if you were to get it right, the
next requirements change tends to hit your house of cards with a large
bucket of water.
And never mind trying to explain the design to other developers. I
currently maintain a critical multi-threaded component (inherited from
another developer who left), and my comment on the design is "I cannot
even properly explain it to myself, let alone someone else". Which is
why I have a new design based on java.util.concurrent queues on the
table.
2) What if you have lots of processors? Does that change the picture
any? That is, if you use isolated processes with message passing and
you have as many processors as you want, do you still think you need
shared-memory threading?
In such a setup I think you usually don't have directly shared memory
at the hardware level, so the processors themselves have to use
message passing to access shared data structures. Which IMHO means
that you might as well design your software that way too.
A comment on the issue of serialization -- note that any time you
need to protect shared memory, you use some form of serialization.
Even optimistic methods guarantee serialization, even if it happens
after the memory is corrupted, by backing up to the uncorrupted
state. The effect is the same; only one thread can access the shared
state at a time.
And a further note on sharing memory via a transactional resource (be
it STM, a database or a single controlling thread).
This situation always introduces the possibility that your update
fails, and a lot of client code is not designed to deal with that. The
most common pattern I see in database access code is to log the
exception and continue as if nothing happened. The proper error
handling only gets added in after a major screwup in production
happens, and the usually only the the particular part of the code
where it went wrong this time.
Kind regards,
Maarten Hazewinkel
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe