[Tutor] threads

Jeff Shannon jeff@ccvcorp.com
Mon Jan 13 15:13:06 2003


Scott wrote:

>On Mon, 13 Jan 2003 03:34:16 -0800 (PST)
>Danny Yoo <dyoo@hkn.eecs.berkeley.edu> wrote:
>
>>Empirically, it seems that multithreaded programs can be either easy
>>or difficult, based on design.  Personally, I think they're hard.  As
>>a concrete anecdote: the source to the excellent classic game "Star
>>Control II" has just been released to the public,
>>    
>>
>
>If *you* think they're hard, maybe I ought to stay far away from them! 
>But looks like for the program I'm trying to create, I have no choice
>really. 
>

IMO, threading can be anywhere from moderately straightforward to 
incredibly brainbending, depending on just how you're using those 
threads.  The trick is to remember that you can't be sure of the timing 
of *anything* that happens in another thread unless you explicitly 
synchronize.  For most purposes, synchronizing threads isn't all that 
difficult, but if you're doing something complex then the 
synchronization issues can quickly become extremely hairy.

One resource that is invaluable for multithreading is the Queue module. 
 Queues are threadsafe methods of passing data back and forth between 
threads.  (Sharing a normal variable between threads is *not* safe, 
because you can never tell when the other thread might clobber your 
variable while you're in the middle of using it...)  One of the standard 
architectures for multithreading is to designate a set of "producer" 
threads and a set of "consumer" threads.  Since you mention sockets, one 
possibility is to hand a socket and one end of a queue to each producer 
thread.  That thread will read data from the socket, package it up, and 
drop it into the queue.  You can safely have several such threads 
dropping data into the same queue.  Now you set up a consumer thread 
that reads data from the queue and then acts on it.  It'll need to keep 
track of *which* socket the data came from (so that information needs to 
be in the packaging), but it doesn't need to worry about *how* to get 
the data.  The synchronization trick comes in because you have no way of 
knowing which data arrived "first", only what socket it came from -- and 
you can be pretty sure (if you're using TCP sockets at least) that the 
data from any given socket is in order.  But if (for example) you're 
receiving long streams of data on two different sockets, you can't be 
sure that you'll get all of stream 1 before stream 2, or vice versa -- 
probably you'll get both streams in many small chunks that are somewhat 
randomly interleaved.

So, again, the trick with threads is to never trust the timing of 
anything, and to be careful any time that threads are doing anything 
that might be interpreted as sharing information.  And be wary of the 
possibility that thread A may be waiting for thread B to provide some 
data, but thread B is blocked waiting for a resource that thread A has 
locked up...

But yes, try it out a bit, keep it simple at first, and feel free to ask 
specific questions here.  :)

Jeff Shannon
Technician/Programmer
Credit International