使用Multiprocess的Join()时遇到阻塞问题

时间:2013-01-17 17:42:44

标签: python multithreading multiprocessing

我不明白为什么以下代码阻塞。我试图简单地循环一段时间,然后发送消息给线程停止。我的流程类如下。

class Worker(multiprocessing.Process):
    def __init__(self, queue):
        multiprocessing.Process.__init__(self)
        self.queue = queue
        self.running = True

    def run(self):
        print 'entered run'
        while self.running:
            print 'thread time:', time.time()
            time.sleep(.6)
        print 'thread end'
        return 0

非常直接。我的主要看起来像这样:

if __name__ == '__main__':
    queue = Queue()
    p = Worker(queue)
    p.daemon = True
    p.start()
    time.sleep(3)
    p.running = False
    print 'Main end'

所以,我期望这个程序要做的是启动进程,它将沿着main的一侧运行自己的循环。当发生这种情况时,Main()将休眠3秒,然后将工作进程内部的循环条件设置为False,以便它突然循环。然后他们都打印出一个很好的“完成”消息,程序退出。但是,问题是main线程在进程有机会显示其消息之前退出。

例如,输出如下所示:

>> entered run
>> thread time: 1358444245.31
>> thread time: 1358444245.91
>> thread time: 1358444246.51
>> thread time: 1358444247.11
>> thread time: 1358444247.71
>> Main end

所以,阅读一点,我看到join()用于阻塞,直到线程完成执行。在此之后,我在断开线程中的循环条件后立即添加join()调用。我的想法是,这将阻止主要进程,直到进程有时间关闭自己。

if __name__ == '__main__':
    queue = Queue()
    p = Worker(queue)
    p.daemon = True
    p.start()
    time.sleep(3)
    p.running = False
    p.join()          ## <------ New Line 
    print 'Main end'

然而,这表现出乎意料。一旦我添加该行,线程永远不会停止执行,因此主要块无限期地停止。以下产出将进入永恒。

>> entered run
>> thread time: 1358444362.44
>> thread time: 1358444363.04
>> thread time: 1358444363.64
>> thread time: 1358444364.24
>> thread time: 1358444364.84
>> thread time: 1358444365.44
>> thread time: 1358444366.04
>> thread time: 1358444366.64
>> thread time: 1358444367.24
>> thread time: 1358444367.84
>> thread time: 1358444368.44
>> thread time: 1358444369.04
>> thread time: 1358444369.64
>> thread time: 1358444370.24

这里发生了什么?为什么当我添加join()时,我的线程是否会突破其循环?

1 个答案:

答案 0 :(得分:2)

首先,multiprocessing.Process不创建Thread,它会创建一个单独的进程来执行提供的函数。

您需要使用multiprocessing.Queue在两个进程之间传递消息。

看看:http://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes

正如Max Yakimets所提到的,您正在修改第一个流程中的值,但从未将消息传递给第二个流程。

您需要在队列中添加项目,而不是更改p.running值。在此过程中,您需要检查队列中是否有任何消息等待并对其作出反应(关闭,执行其他操作等)。