我正在开发一个涉及多个套接字和线程/进程的复杂应用程序。出于某种原因,有时这个特定的进程不会运行,除非调用延迟。
类似于:
class MyClass:
def somefunc(self):
some_thread = Thread(...) # Some complex processing.
some_thread.start()
time.sleep(1) # Some delay like this is needed.
some_process = Process(target=sometarget)
print('Should start')
some_process.start()
print('Should have started')
def sometarget(self):
print('It started')
# Do more complex processing here.
这会打印出类似于:
Should start
Should have started
It started # This gets printed out only if there's a significant delay inserted
由于Python在下面调度作业的方式,不确定这是否只是随机发生的,但如果我不延迟,即使我等了一段时间,它似乎也不会运行。
当您使用线程时,您会遇到"全局解释器锁定";。Python解释器一次只允许一个线程运行Python代码。在睡眠或阻塞I/O之前,主线程将继续运行,线程将等待。Python线程对于I/O绑定负载非常好,但对于CPU绑定负载几乎毫无用处。这就是为什么人们使用多处理的原因,在多处理中,您实际上是在一个独立的进程中运行一个独立解释器。
请参阅我对您的问题的评论以及Tim Roberts关于全局解释器锁(GIL(的回答。我可以看到这样一种场景,启动的线程("一些复杂的处理"(锁定了GIL,阻止了主线程继续运行并获得启动进程创建语句的机会。但是它可能也没有机会执行延迟语句(time.sleep(1)
(。如果真的发生了,那会有什么结果呢?如果有什么不同的话,那么这个延迟需要在启动的线程中,这样它才能释放GIL并允许主线程运行。但我发现,没有必要插入这种延迟。我假设即使线程被创建并且";"启动";,主线程继续运行,并在新线程实际开始执行之前创建新进程。
这个是一个完整、最小、可重复的例子:
from threading import Thread
from multiprocessing import Process
import time
def doWork():
# 100% CPU-bound
sum = 0
for _ in range(100_000_000):
sum += 1
class MyClass:
def somefunc(self):
some_thread = Thread(target=doWork) # Some complex processing.
some_thread.start()
#time.sleep(1) # Some delay like this is needed.
some_process = Process(target=self.sometarget) #self.sometarget is needed
print('Should start')
some_process.start()
print('Should have started')
def sometarget(self):
print('It started')
# this is required for Windows, which I have:
if __name__ == '__main__':
mc = MyClass()
mc.somefunc()
打印:
Should start
Should have started
It started