
Threads, slow and buggy - uriel
http://www.and.org/texts/threads
======
axod
Interesting article.

Threads should always be an absolute last resort. Programmers working on
concurrency, locking, etc are often solving self inflicted problems. I don't
know why they do it.

edit:

I've mentioned it in the past, and I do hate harping on about mibbit ;) but I
had a similar experience there - as you can imagine, a large amount of dns
lookups (both forward and reverse) are required. First version used a single
separate thread to do them. Had to do lots of synchronization in the callback.
2nd ver had a threadpool, which was even more complex. Still slow as hell.

Final version, and the version in use now uses async nio in the main network
thread, and is as fast as fast can be. The code is far simpler/faster than the
threaded version, and handles thousands of lookups with minimum of fuss.
There's just an initial investment of writing dns packet+udp code (Not rocket
science).

At first glance, threads often seem like the 'easy' option. Often they're not.
In my example, it was far easier just to knuckle down and write a simple async
dns client than constantly mess around with concurrency issues and try and get
it to go fast.

The code in this article looks horrible to work with, and reminds me of how my
first version looked :/

~~~
smanek
The problem, in my mind, is that many languages provide 'transparent' shared
state between the threads - which can easily introduce very subtle bugs.

The simple solution is to requires any sharing of state to be made explicit
(e.g., message passing). This obviously introduces some overhead, but I think
it could eventually become like assembler v. higher level languages. A handful
of very talented hackers will still be always be able to beat any threading
abstraction by manually dealing with everything - but the abstractions will
get more and more optimizations (e.g., copy-on-write variables, more static
analysis) until you rarely bother looking underneath them.

~~~
silentbicycle
Either that, or only use co-operative (not pre-emptive) multitasking via
coroutines. Specifying the points at which control is allowed to switch from
one to another is far easier than trying to reliably specify where it cannot
and using locks.

Message-passing works quite well, but coroutines are also a viable option. The
problems come from using pre-emptive threads AND shared state, because
reasoning about who is modifying what (and at what stage of completion)
becomes difficult. Co-routines avoid the former, message passing the latter.
Which is simpler overall depends on the problem.

~~~
uriel
> Message-passing works quite well, but coroutines are also a viable option.

Why not both as in CSP/Limbo? ;)

Edit: Note that you can get both in C too using the confusingly named
libthread(2) <http://man.cat-v.org/plan_9/2/thread> (Also available in Unix as
part of Plan 9 from User Space <http://plan9.us> )

~~~
silentbicycle
You can do either in Lua pretty easily, too. Doing _both_ doesn't make much
sense, though - schlepping around large data structures in message-passing can
be a performance problem, but unlike coroutines, can be very easily switched
to a run over multiple machines.

Coroutines are in the core language, and there's also ConcurrentLua
(<http://concurrentlua.luaforge.net/>) for message passing.

~~~
uriel
> schlepping around large data structures in message-passing can be a
> performance problem,

Not really, it is not too hard to implement it locally as passing pointers
around.

------
bwd
The quality of the argument against mutlithreading is undermined quite a bit
by choosing one of the most poorly written networking library functions
around. If you want to do this right, use libevent or Boost.Asio asynchronous
resolvers.

I do have to admit that I didn't bother to dig through the final example
looking for the errors, so perhaps the author did have a better argument in
there but didn't bother to pursue it more aggressively.

------
illumen
Using non-threadsafe calls with threads... yeah, that's not going to be nice.

