2

如果访问两个线程都可以工作,但是当它们一起执行时halt_listener将垄断不允许import_1执行的资源。最终目标是让 halt_listener 侦听终止消息,然后将运行变量设置为 false。当我向halt_listener 发送管道时,这很有效,但我更喜欢队列。

这是我的代码:

import multiprocessing 
import time 
from threading import Thread

class test_imports:#Test classes remove 
      alive = {'import_1': True, 'import_2': True};

      def halt_listener(self, control_Queue, thread_Name, kill_command):
          while True:
              print ("Checking queue for kill")
              isAlive = control_queue.get()
              print ("isAlive", isAlive)
              if isAlive == kill_command:
                 print ("kill listener triggered")
                 self.alive[thread_Name] = False;
                 return

      def import_1(self, control_Queue, thread_Number):
          print ("Import_1 number %d started") % thread_Number
          halt = test_imports()
          t = Thread(target=halt.halt_listener, args=(control_Queue, 'import_1', 't1kill'))
          count = 0 
          t.run()
          global alive 
          run = test_imports.alive['import_1'];
          while run:
                print ("Thread type 1 number %d run count %d") % (thread_Number, count)
                count = count + 1
                print ("Test Import_1 ", run)
                run = self.alive['import_1'];
          print ("Killing thread type 1 number %d") % thread_Number 

我错过了什么吗?

4

1 回答 1

5

问题是您正在调用t.run(). run不是启动线程的方法;run是要在线程上运行的实际代码。通过直接调用它,您正在线程上运行它并等待它完成。

你想要的是t.start().

有关详细信息,请参阅文档threading.Thread


在我们处理它的同时,您的代码还有一些其他问题。

首先,您周围没有锁self.alive。您不能在一个线程中更改一个值(除了少数自动自同步的类型,如Queue)并在另一个线程中访问它而无需锁定。你经常会侥幸成功,但在多线程程序中“经常”只是意味着它在你的大演示之前不会失败,然后在你开始修复它之前需要数周时间来弄清楚如何重现......(在在这种情况下,条件可能比锁更有意义,但无论哪种方式,您都需要同步某些东西。)

同时,尽可能快地循环轮询self.alive['import_1']将无缘无故地消耗 100% 的 CPU。几乎总是有更好的方法来等待某事(例如,在这种情况下,如果您使用 Condition 进行同步,您也可以在此处使用它来等待);在极少数情况下,如果没有,您至少应该sleep每次都通过循环。

alive实际上是类属性而不是实例属性。这通常不是你想要的。实际上,您尝试同时访问test_imports.aliveand self.alive,但只要您从未分配给它,这两个最终都会成为类属性,这使得它更加混乱。然后,最重要的是,你有一个同名的全局变量,这只是造成极度混乱的一个原因。

此外,这看起来像 Python 2 代码,但在某些情况下,您就像使用print函数一样使用它——例如,print ("isAlive", isAlive). 这不会做你想做的事——而不是打印类似的东西isAlive command,它会打印类似的东西('isAlive', 'command'),这不是很漂亮。同时,像这样的表达式中多余的括号("Import_1 number %d started") % thread_Number意味着有人必须阅读几次才能说服自己括号实际上并没有做任何事情。

最后,为什么要创建一个单独的test_imports实例来调用halt_listener?显然,这两种方法试图通过 on 的属性进行通信self,但如果在两个不同的对象上调用它们,它们就不会这样做。为什么不只是target=self.half_listener

于 2013-08-21T00:14:57.753 回答