Is python's print synchronized?
Is python's pr开发者_如何学Cint synchronized? :)
Between Threads.
Python's print isn't even vaguely thread safe. (Bram Cohen's words, not mine.)
if you call print
from multiple threads, the output may be interleaved at the whim of the scheduler.
The answer is no, threads can interrupt each other. However, you can use locks to avoid that.
lock's prevent threads from interrupting each other on global things (specifically here the output screen) when a thread want's to use global thing with a lock, it first checks if the lock is unlocked, if not it waits until it is, after that it locks the lock, do the stuff it want's to do with the global thing, and finally release the lock.
However, don't just use flag variables and if checks to implement this, the threads can switch between the if statement and the locking. Python implements a lock class, if I remember correctly its threading.lock.
Also, note that you can run into a deadlock or a livelock if you don't use locks correctly. I don't have much time now so I can't really explain all that here, but you can google that for more info, I'll also check if I can share presentations from my last year's course in university, they explain that pretty good in there.
Kind of workaround... It does not print synchronized, but it is monolithic and thus the threads will not write on top of each other.
Pros: Does not require locking and thus is faster.
Cons:
- It is not synchronized and there is no guarantee the events will be printed in the order happened. As a side effect, if an exception appears, the text of the exception might start before the last few prints are out. They might show up after the exception text or somewhere in the middle of the stack trace.
- Takes a bit more time and memory to run the loop.
import threading, time
class SomeThread(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
...
def mono_print(self, *v):
p = time.strftime("%Y-%m-%d %H:%M:%S") + ' ' + self.name
for s in v:
p += ' ' + str(s)
print(p + '\n', end='', flush=True)
def run(self):
self.mono_print('thread is running.')
...
self.mono_print('something', 'them something else')
...
self.mono_print('processed')
精彩评论