>>>>> Andreas Grommek <a...@mozarellasalat.homelinux.net> (AG) wrote:
>AG> Hi Newsgroup, >AG> I'm new to python and I am familiarizing myself with threads >AG> (haven't done any threading in any other language before...). I was >AG> playing around and discovered some weird behavior. Here is my code: When you start programming with threads you should familiarize yourself with (or better: study) the subject of parallel programming. Without that you will make hard to find and debug errors. Fortunately this one you did find. Many of these have to do with 'shared resources', i.e. resources (like objects) that are used in more than one thread at the same time, while at least one thread modifies it/them. For a start read this: http://effbot.org/zone/thread-synchronization.htm and then read some more elaborate literature. >AG> import threading >AG> from time import sleep >AG> from random import random >AG> import sys >AG> class MyThread(threading.Thread): >AG> def __init__(self, t, s): >AG> self.threadmarker = t >AG> self.sleeptime = s >AG> threading.Thread.__init__(self) >AG> def run(self): >AG> print("Tread", self.threadmarker, "is going to sleep for a >while...") >AG> sys.stdout.flush() #flush I/O >AG> sleep(self.sleeptime) #go to sleep >AG> print("Tread", self.threadmarker, "is waking up and terminating") What happens here is that stdout is a shared resource that you are modifying in different threads. So you have to protect it. >AG> a = 1 >AG> b = 20 >AG> for n in range(a, b): >AG> x = MyThread(n,random()*10.0) >AG> x.start() >AG> This should create some threads which print messages, go to sleep for a >random amount of time (max >AG> 10 seconds) and return with a message. When I run the code I get something >like this (always different): You can get even weirder stuff, like: ('Tread', 1, 'is going to sleep for a while...') ('Tread', 2, 'is going to sleep for a while...') ('Tread', 3, 'is going to sleep for a while...') ('Tread', 4, 'is going to sleep for a while...') ('Tread', 5, 'is going to sleep for a while...') ('Tread', 6, 'is going to sleep for a while...') ('Tread', 7, 'is going to sleep for a while...') ('Tread', 8('Tread', , 'is going to sleep for a while...'9, )'is going to sleep for a while...' ('Tread'), 10, 'is going to sleep for a while...') ('Tread'('Tread', 12, 'is going to sleep for a while...') , 11, 'is going to sleep for a while...') ('Tread', 13, 'is going to sleep for a while...') ('Tread', 14, 'is going to sleep for a while...') ('Tread', 15, 'is going to sleep for a while...') ('Tread', 16, 'is going to sleep for a while...') ('Tread', 17, 'is going to sleep for a while...') ('Tread'('Tread', 19, 'is going to sleep for a while...') , 18, 'is going to sleep for a while...') ('Tread', 10, 'is waking up and terminating') ... Here is a solution using locks (and at the same time I corrected Tread->Thread class MyThread(threading.Thread): def __init__(self, t, s, lock): self.lock = lock self.threadmarker = t self.sleeptime = s threading.Thread.__init__(self) def run(self): with lock: print("Thread", self.threadmarker, "is going to sleep for a while...") sys.stdout.flush() #flush I/O sleep(self.sleeptime) #go to sleep with lock: print("Thread", self.threadmarker, "is waking up and terminating") a = 1 b = 20 lock = threading.Lock() for n in range(a, b): x = MyThread(n,random()*10.0, lock) x.start() If you have an older version of Python you have to replace with lock: statement by lock.acquire() try: statement finally: lock.release() or if you want to risk deadlocks: lock.acquire() statement lock.release() -- Piet van Oostrum <p...@cs.uu.nl> URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4] Private email: p...@vanoostrum.org -- http://mail.python.org/mailman/listinfo/python-list