Threading for a newbie

Scott David Daniels scott.daniels at acm.org
Thu Jan 5 19:53:12 EST 2006


Koncept wrote:
> Hi. I am fairly new to Python programming and am having some trouble
> wrapping my head around threading.
Threading sounds simpler than it is.

Here is a classic Pythonic solution related to yours:

> What I would like to learn from this example is how to use threads to
> call on other classes and append/modify results in a list outside of
> scope (basically keep track of variables throught the total threading
> process and return them somehow afterwards ). I was thinking about
> using some sort of global, but I am not sure what the best approach to
> this is.
You generally want to avoid mutation of anything in more than one
thread, and prefer to only share reading between threads.  The only
time you can do more than that is when you _know_ the modification
is "atomic" -- there is no chance another thread can "see" a
half-modified value.

One Pythonic way to do this is to talk to a results-gathering thread
through a Queue (which was designed to handle these inter-thread
issues).  I'll just hack up your code a bit.

     import time, random, threading, Queue
     base = time.time()  # just to make time printing simpler


     class Server(threading.Thread):

         def __init__(self, name, source, destination):
             threading.Thread.__init__(self, name=name)
             self.name = name
             self.source = source
             self.destination = destination

         def run(self):
             while True:
                 command = self.source.get()
                 if command is None:
                     break    # Told to stop
                 result = self.compute(command)
                 self.destination.put(result)
             self.destination.put(None)

         def compute(self, operation):
             sleep = random.uniform(1, 6)
             time.sleep(sleep)
             return '%s: %s at %s' % (self.name, operation, time.time() 
- base)


     def main(servers):
         starting = time.time()
         commands = Queue.Queue()   # Things to do go here
         results = Queue.Queue()    # results of processing comes out here

         # Start up servers waiting for input
         for n in range(servers):
             thread = Server('s%s' % n, commands, results)
             thread.start()

         # throw in a bunch of work to be done.
         for person in ['Bill', 'Jane', 'Steve', 'Sally', 'Kim']:
             commands.put(person)

         # throw in a stop command for each server.
         for n in range(servers):
             commands.put(None)

         while True:
             result = results.get(True, 10.5)
             if result is None:
                 # A server stopped (no more work to do)
                 servers -= 1       # one fewer server
                 if 0 == servers:   # If no servers left, we're done
                     return     # All servers are done.
             else:
                 # We got a result.
                 print '%s: %s' % (time.time() - base, result)


     if __name__ == "__main__":
         main(3)

--Scott David Daniels
scott.daniels at acm.org



More information about the Python-list mailing list