> Don't write multi-threaded programs (and that includes using asynch i/o)
> unless you've passed a college-level exam on doing it.
uh oh. pet peeve alert.
personally, i think that advice is misguided. yes, multi-threaded programs
are hard to get right. but then that applies to almost everything programmers
have to do. i'd say it's certainly better than the alternative, i.e., having
a program that beachballs all the time, because it performs long-running tasks
in the gui thread that should have been spun off independently. in fact, i
think i'd go completely the other way, and say it's almost impossible to write
anything but toy programs that are *not* multi-threaded.
here's the trick, as i see it: make your threads completely independent from
each other. if you're going to spawn a secondary thread, have it pull jobs
out of a locked input queue, and don't let it share any objects with your main
thread. or launch a thread to do just one task, and it suicides when
finished. when the thread needs to report its results, you can use [NSObject
performSelectorOnMainThread] or something similar.
in the heat of the moment, it's easy to think it'll be okay to share an object
"just this once," and put a lock around it. and now you're that much closer
to the embrace of death, where thread 1 has locked object A and is trying to
lock object B, and thread 2 has locked object B and is trying to lock object
A, and now both threads are dead until you kill the program. that's the most
common beginner's mistake in multi-threading, i think. it's a wicked-hard
kind of problem to debug, because it probably only happens when the program is
under extreme stress, and you won't be able to duplicate it reliably. i used
to fall victim to that one a lot. the usual answer is: if you always lock
objects in the same order, it won't happen. eh, i don't think that's
feasible. you have to make use of too much knowledge that you're officially
not supposed to know, it breaks encapsulation. so now i structure my
multi-threaded code so that no thread is ever holding more than one lock at a
time. i almost never introduce new locks, i use them only for input queues.
yes, it's inconvenient, but i never have to worry about the embrace-of-death
problem.
it's not surprising to me that many programmers have the attitude that you do,
that threading is so hard that it should be avoided altogether. that seems to
mostly be the attitude of the people making the OSes, as well! every OS i've
ever used made threading much more difficult than it should be, *except* for
beos. that one was architected from the very first line of code to be
multi-threaded, and it shows. your advice would be completely useless there,
because it's impossible to write a beos gui program that is *not*
multi-threaded. every beos window runs in its own thread. but they make it
much more difficult to screw up, as well. each window has its own
self-locking queue of input events. by comparison, macosx's thread support
feels bolted on.
i'd say learning threading is easier than another common and difficult task:
large program management. when a project gets up to around 40 or 50 thousand
lines, you have to start thinking long and hard about program organization, or
else you're going to have such a big mess on your hands that you can't fix a
bug without introducing two more. i bet a lot of amateur projects end up
dying that way. so that's another issue that doesn't get as much attention as
it should, and with similar bad results: amateurs are prevented from writing
projects that get past a certain size.
so i guess i'd agree to the extent that you can't just say "hey, i think i'll
add some threads to my program," because you'll probably screw it up the first
time. so don't do that in a bread-and-butter app that you're selling to
people. but then that's true of pretty much everything new you try, isn't it?
i bet your very first mac program didn't exactly rival photoshop, am i right?