使用线程和队列时格式不正确
Improper formatting while using threading and queues
我在下面写的代码应该输出类似这样的东西:
<Floor(Thread-3, started 44660)> <Bank(Thread-1, started 43356)> shutting down
<Floor(Thread-4, started 44108)> received a message: shutting down (0, 'UP')
<Bank(Thread-1, started 43356)> received a message: (1, 'DOWN')
<Bank(Thread-1, started 43356)> shutting down
<Bank(Thread-2, started 27800)> shutting down
但是,输出的格式有时似乎不一致。例如:
<Floor(Thread-3, started 27076)> <Bank(Thread-1, started 44608)>shutting down
<Floor(Thread-4, started 28772)>received a message: (shutting down0, 'UP')
<Bank(Thread-1, started 44608)> received a message: (1, 'DOWN')
<Bank(Thread-1, started 44608)> shutting down
<Bank(Thread-2, started 41480)> shutting down
在大多数程序中,一致的数据很重要。为什么这个输出不一致,我该如何防止它?
import threading
import Queue
banks = []
floors = []
class Bank(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.mailbox = Queue.Queue()
banks.append(self.mailbox)
def run(self):
while True:
data = self.mailbox.get()
if data == 'shutdown':
print self, 'shutting down'
return
print self, 'received a message:', data
def stop(self):
banks.remove(self.mailbox)
self.mailbox.put('shutdown')
self.join()
class Floor(threading.Thread):
def __init__(self, number = 0):
threading.Thread.__init__(self)
self.mailbox = Queue.Queue()
floors.append(self.mailbox)
self.number = number
def run(self):
while True:
data = self.mailbox.get()
if data == 'shutdown':
print self, 'shutting down'
return
print self, 'received a message:', data
def stop(self):
floors.remove(self.mailbox)
self.mailbox.put('shutdown')
self.join()
def call(self, data):
banks[0].put((self.number, data))
b0 = Bank()
b1 = Bank()
b0.start()
b1.start()
f0 = Floor(0)
f1 = Floor(1)
f0.start()
f1.start()
f0.call('UP')
f1.call('DOWN')
f0.stop()
f1.stop()
b0.stop()
b1.stop()
最终,由于您的 call()
调用现在在不同的线程中执行,因此无法保证它们将同步执行(和输出)。如果你想保证输出不交错,你需要在你的打印调用周围放置一个大的全局锁(互斥锁)。
即使这样也不能保证它们的顺序一致 - 例如上面的不同线路可以很容易地切换 - 在这种情况下你需要锁定你的电话。顺便说一句,这首先会抵消多线程的几乎所有性能优势。
print
不是线程安全的。然而,sys.stdout.write
是。
这确实解决了交织的直接问题,但我怀疑这是最合适的方法。
我在下面写的代码应该输出类似这样的东西:
<Floor(Thread-3, started 44660)> <Bank(Thread-1, started 43356)> shutting down
<Floor(Thread-4, started 44108)> received a message: shutting down (0, 'UP')
<Bank(Thread-1, started 43356)> received a message: (1, 'DOWN')
<Bank(Thread-1, started 43356)> shutting down
<Bank(Thread-2, started 27800)> shutting down
但是,输出的格式有时似乎不一致。例如:
<Floor(Thread-3, started 27076)> <Bank(Thread-1, started 44608)>shutting down
<Floor(Thread-4, started 28772)>received a message: (shutting down0, 'UP')
<Bank(Thread-1, started 44608)> received a message: (1, 'DOWN')
<Bank(Thread-1, started 44608)> shutting down
<Bank(Thread-2, started 41480)> shutting down
在大多数程序中,一致的数据很重要。为什么这个输出不一致,我该如何防止它?
import threading
import Queue
banks = []
floors = []
class Bank(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.mailbox = Queue.Queue()
banks.append(self.mailbox)
def run(self):
while True:
data = self.mailbox.get()
if data == 'shutdown':
print self, 'shutting down'
return
print self, 'received a message:', data
def stop(self):
banks.remove(self.mailbox)
self.mailbox.put('shutdown')
self.join()
class Floor(threading.Thread):
def __init__(self, number = 0):
threading.Thread.__init__(self)
self.mailbox = Queue.Queue()
floors.append(self.mailbox)
self.number = number
def run(self):
while True:
data = self.mailbox.get()
if data == 'shutdown':
print self, 'shutting down'
return
print self, 'received a message:', data
def stop(self):
floors.remove(self.mailbox)
self.mailbox.put('shutdown')
self.join()
def call(self, data):
banks[0].put((self.number, data))
b0 = Bank()
b1 = Bank()
b0.start()
b1.start()
f0 = Floor(0)
f1 = Floor(1)
f0.start()
f1.start()
f0.call('UP')
f1.call('DOWN')
f0.stop()
f1.stop()
b0.stop()
b1.stop()
最终,由于您的 call()
调用现在在不同的线程中执行,因此无法保证它们将同步执行(和输出)。如果你想保证输出不交错,你需要在你的打印调用周围放置一个大的全局锁(互斥锁)。
即使这样也不能保证它们的顺序一致 - 例如上面的不同线路可以很容易地切换 - 在这种情况下你需要锁定你的电话。顺便说一句,这首先会抵消多线程的几乎所有性能优势。
print
不是线程安全的。然而,sys.stdout.write
是。
这确实解决了交织的直接问题,但我怀疑这是最合适的方法。