python线程连接没有正确发生

时间:2013-04-16 12:12:21

标签: python multithreading

import threading
import Queue

q = Queue.Queue()
class Worker( threading.Thread ):
    def __init__( self, q ):
        threading.Thread.__init__( self )
        self.q = q

    def run( self ):
        while True:
            print '%s waiting for data' % self.getName()
            data = self.q.get()
            print '%s data fetched from queue %s' % ( self.getName(), data )
            if data == 'shutdown':
                print '%s shutting down in %s' % ( self.getName(), self )
                return
            print '%s received a message: %s' % ( self.getName(), data )

    def stop( self ):
        self.q.put( "shutdown" )

#        self.join()  # If I uncomment this line, then sometimes the program does not complete.


def broadcast_event( data ):
    q.put( data )

t1 = Worker( q )
t2 = Worker( q )
t1.start()
t2.start()
broadcast_event( "first event" )
broadcast_event( "second event" )

t1.stop()
t2.stop()

我正在尝试理解python中的线程,并且我陷入了多线程队列示例中。 我想做什么: -

  1. 使用单个队列对象创建2个线程
  2. 现在,我在队列中放入了2个不同的数据条目(使用broadcast_event函数)
  3. 现在,在stop方法中,有一条注释行,我将线程加入主程序。
  4. 但是,当我取消注释self.join行时,程序会挂起并永远运行。但是,如果我删除了self.join,则效果非常好。

    我想了解我是否尝试使用加入是否存在问题。

2 个答案:

答案 0 :(得分:3)

问题是两个线程都使用相同的队列。死锁场景是:

  1. 主线程在'shutdown'
  2. 中发送t1.stop()
  3. t2'shutdown'
  4. 读取q
  5. 主线程加入t1,它正在等待新邮件。
  6. 您可以通过制作2个队列或执行前两个shutdown消息然后两个连接来解决此问题。

答案 1 :(得分:1)

问题是你有两个线程使用一个队列。当您put队列中的消息时,您无法分辨哪些线程消耗它。当您调用stop(),将"shutdown"添加到队列时,任何线程都可能会使用它,而不一定是您想要的线程。

结果可能是另一个线程正在退出,而你join错了。

一种可能的解决方案是首先将shutdown放入队列N次(N =线程数),然后将它们全部加入。

for i in range(N):
  q.put("shutdown")
for t in threads:
  t.join()

更好,更强大的解决方案是避免将关闭消息传递到队列中。您可以使用self.should_stop属性,在run中定期检查此属性。