simple threading question
I started to approach multi threading, but I need something confirmed. For my testing purposes, I am using python 2.7.11 on Linux.
I put something really simple together. Two threads start at the same time and count to 9. One starts counting at 1 and the other one starts at 2.
import threading
class myThread(threading.Thread):
def __init__(self,threadId):
threading.Thread.__init__(self)
self.threadId=threadId
def run(self):
while self.threadId < 10:
print self.threadId
self.threadId+=1
thread1=myThread(1)
thread2=myThread(2)
thread1.start()
thread2.start()
My expectation was line by line counting to 9. The output sometimes looks like this:
1
22
3
34
5
46
7
58
6
9
7
8
9
Apparently, they can write in the same line while the other process is still going on? The line breaker does not always get called properly. Is this as expected?
For testing purposes I changed:
print self.threadId
to
print "cookies", self.threadId
Now the output looks like this:
cookiescookies 12
cookies 3cookies 2
cookies cookies 4
3cookies 5
cookies 4cookies
6cookies 5
cookies 7cookies 6
cookies 8cookies 7
cookies cookies 89
cookies 9
It looks like, we at do not overwrite "cookies". For my next test, I changed:
print "cookies", self.threadId
to
temp="cookies cake", self.threadId
print temp
The output is even more all over the place: (('cookies cake', 'cookies cake', 21))
('cookies cake'('cookies cake', , 3)2
)
('cookies cake'('cookies cake', , 43))
('cookies cake'('cookies cake', , 45))
('cookies cake'('cookies cake', 6)
, 5)
('cookies cake'('cookies c, ake'7)
('cookies cake', 8)
('cookies cake', 9)
, 6)
('cookies cake', 7)
('cookies cake', 8)
('cookies cake', 9)
Is this as expected? Because "duh this is multi threading?"
6 comments · 88% upvoted · other discussions
Yes, print is not thread-safe.
baidarkajoe 5 points · Dec 2015
As far as I know, print is safe in that it's not going to crash or corrupt program state, but it's possible for a print call to occur in the middle of another print call.
A common solution to this problem is to have one thread dedicated to user interaction. The other threads can use a queue to pass items to the dedicated thread.
For example:
Then in your other threads:
(Note that it would be more flexible to pass the Queue as an argument to __init__ and store it as an attribute of your class instance. That way you don't depend on a global object. This is just an example. The global object is probably ok for a one-off script, anyway.)
One other thing: you should be calling the parent class __init__ method in your subclass. Something like this:
or even
This is so anything normally done by the default __init__ routine is still taken care of. According to the threading module docs, it's required, although the call to run() seems to take care of it.