[英]Python thread execution blocking other threads
Both threads work if accessed but when they are executed together halt_listener
will monopolize the resources not allowing import_1
to execute. 如果两个线程都被访问,则它们都起作用,但是当它们一起执行时, halt_listener
将垄断资源,从而不允许import_1
执行。 The end goal is to have halt_listener listen for a kill message and then set a run variable to false. 最终目标是让halt_listener监听一条kill消息,然后将运行变量设置为false。 This has worked when I was sending a pipe to the halt_listener but I prefer a queue. 当我将管道发送到halt_listener时,此方法已奏效,但我更喜欢队列。
Here is my code: 这是我的代码:
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
Am I missing something? 我想念什么吗?
The problem is that you're calling t.run()
. 问题是您正在调用t.run()
。 run
isn't a method that starts a thread; run
不是启动线程的方法; run
is the actual code that's meant to run on the thread. run
是要在线程上run
的实际代码。 By calling it directly, you're running it on your thread, and waiting for it to finish. 通过直接调用它,你运行它在你的线程,并等待它完成。
What you want is t.start()
. 您想要的是t.start()
。
See the documentation on threading.Thread
for details. 有关详细信息,请参见关于threading.Thread
的文档。
While we're at it, there are a few other problems with your code. 在我们讨论过程中,您的代码还有其他一些问题。
First, you don't have a lock around self.alive
. 首先,您没有对self.alive
的锁定。 You can't change a value (except for a small number of automatically-self-synchronized types like Queue
) in one thread and access it in another without a lock. 您无法在一个线程中更改值(除了少数自动自我同步的类型,例如Queue
),而不能在没有锁的情况下访问另一个线程。 You will often get away with it, but "often" in a multithreaded program just means it won't fail until your big demonstration, and it will then take weeks to figure out how to reproduce before you can even begin fixing it… (In this case, a Condition might make more sense than a Lock, but either way, you need to synchronize on something .) 您通常会无所适从,但是“经常”在多线程程序中只是意味着它直到您的大型演示才会失败,然后您将需要数周的时间弄清楚如何进行复制,甚至可以开始对其进行修复……(在在这种情况下,“条件”可能比“锁定”更有意义,但是无论哪种方式,您都需要在某些事物上进行同步。)
Meanwhile, looping as fast as possible to poll self.alive['import_1']
is going to burn 100% CPU for no good reason. 同时,尽可能快地循环以轮询self.alive['import_1']
将self.alive['import_1']
消耗100%的CPU。 There's almost always a better way to wait on something (eg, in this case, if you used a Condition for synchronization, you could also use it for waiting here); 几乎总是有一种更好的方法来等待某事(例如,在这种情况下,如果您使用条件进行同步,则也可以在这里等待它); in the rare cases when there isn't, you should at least sleep
every time through the loop. 在极少数情况下,如果没有,至少每次循环时都应该sleep
。
alive
is actually a class attribute rather than an instance attribute. alive
实际上是一个类属性,而不是实例属性。 That's usually not what you want. 通常这不是您想要的。 In fact, you try to access both test_imports.alive
and self.alive
, but both of those will end up being the class attribute as long as you never assign to it, which makes it more confusing. 实际上,您尝试同时访问test_imports.alive
和self.alive
,但是只要您从未分配它们,它们最终都将成为class属性,这会使它更加混乱。 And then, on top of that, you have a global with the same name, which is just a recipe for extreme confusion. 然后,最重要的是,您有一个具有相同名称的全局名称,这只是极度混乱的秘诀。
Also, this looks like Python 2 code, but you're using print
as if it were a function in some cases—eg, print ("isAlive", isAlive)
. 同样,这看起来像Python 2代码,但是您在某些情况下使用print
好像它是一个函数,例如print ("isAlive", isAlive)
。 This isn't going to do what you want—instead of printing something like isAlive command
, it's going to print something like ('isAlive', 'command')
, which is not very pretty. 这不会做您想要的事情,而不是打印类似isAlive command
东西,而是打印类似('isAlive', 'command')
,这不是很漂亮。 And meanwhile, the extra parentheses in expressions like ("Import_1 number %d started") % thread_Number
mean that someone has to read that over a few times to convince themselves that the parentheses aren't actually doing anything. 同时, ("Import_1 number %d started") % thread_Number
等表达式中的多余括号表示某人必须多次阅读才能使自己确信括号实际上没有做任何事情。
Finally, why are you creating a separate test_imports
instance to call halt_listener
on? 最后,为什么要创建一个单独的test_imports
实例来调用halt_listener
? Clearly the two methods are trying to communicate through attributes on self
, but they're not going to do that if they're called on two different objects. 显然,这两种方法试图通过self
属性进行通信,但是如果在两个不同的对象上调用它们,它们将不会这样做。 Why not just target=self.half_listener
? 为什么不只是target=self.half_listener
?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.