<p><code>join</code>在概念上相当简单-<code>x.join</code>表示“当前执行线程(即进程)在<code>x</code>终止之前,不能越过这个<em>点。”</p>
<p>因此,一般情况下,您不希望<strong>main</strong>线程继续超过某个点,直到您的所有工作人员都完成了他们的工作。由于您在主线程中执行<code>task0</code>,因此执行<code>join</code>会阻止主线程继续超过该点,直到您的所有工作线程(包括<code>task1</code><em>和</em><code>task2</code>)都完成。在</p>
<h2>但是等等,我没有<code>join</code>在<code>task1</code>里!在</h2>
<p>没错。但是<code>task1</code>的进程在其所有的<code>task2</code>完成之前仍然不会终止。这与<a href="http://en.wikipedia.org/wiki/Process_group" rel="nofollow"><em>process groups</em></a>的POSIX概念有关,父进程在其所有子进程终止之前不会终止。那么,让我们看看这个简化示例的输出:</p>
<pre><code>import multiprocessing as mp
from time import sleep
def task2():
sleep(1)
print "I am doing something important."
def task1():
for i in range(2):
process = mp.Process(target=task2)
process.start()
print 'task1 done'
def task0():
process = mp.Process(target=task1)
process.start()
process.join()
if __name__ == '__main__':
task0()
print 'all done'
</code></pre>
<p>输出:</p>
^{pr2}$
<p>如您所见,<code>task1</code>到达了它的结尾,但直到它的子进程结束才终止——这意味着我们在<code>task0</code>中的<code>join</code>块正确地阻止了我们的主线程在所有worker都终止之前终止。在</p>
<p>有趣的是,当运行没有<code>join</code>的原始脚本时,<code>ps jf</code>的输出是<code>join</code>,只有<em>的修改是<code>time.sleep</code>被扔到{<cd7>}中,这样我就可以捕捉到它的运行:</p>
<pre><code> PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
6780 7385 7385 7385 pts/11 7677 Ss 1000 0:00 bash
7385 7677 7677 7385 pts/11 7677 R+ 1000 0:00 \_ ps jf
6780 6866 6866 6866 pts/7 7646 Ss 1000 0:00 bash
6866 7646 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7646 7647 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7647 7672 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7647 7673 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7647 7674 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7647 7675 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7647 7676 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7646 7648 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7648 7665 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7648 7666 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7648 7667 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7648 7668 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7648 7669 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7646 7649 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7649 7656 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7649 7657 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7649 7658 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7649 7659 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7649 7660 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7646 7650 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7650 7652 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7650 7653 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7650 7654 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7650 7655 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7650 7670 7646 6866 pts/7 7646 S+ 1000 0:00 | \_ python test
7646 7651 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7651 7661 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7651 7662 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7651 7663 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7651 7664 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
7651 7671 7646 6866 pts/7 7646 S+ 1000 0:00 \_ python test
</code></pre>
<p>您可以看到,我们的主进程(执行<code>task0</code>)和“第一个子进程”(完成<code>task1</code>的那些)仍然活着,尽管它们显然没有足够的python代码来执行。它们也是同一进程组(<code>TPGID</code>)的所有成员。在</p>
<h2>总结一下,伙计</h2>
<p>所有这些都是一种冗长的说法:主线程中的<code>join</code>通常是您所需要的,因为您可以保证任何子进程在其自身终止之前都会等待<em>它们的</em>子进程终止。在</p>