首页 > 解决方案 > Perl:从并行线程派生

问题描述

下面的代码应该运行 2 个并行线程,每个线程执行 fork(),等待子进程完成,然后线程应该加入(完成)并打印结果。实际上,第一个分叉子进程按预期完成,但第二个子进程挂在 _mutex_lock() 试图退出,因此第二个线程永远不会加入,直到您使用 -9 信号手动杀死第二个子进程。有人可以解释为什么会发生这种情况,以及如何避免这种情况吗?

use strict;
use warnings;
use threads;
use Data::Dumper;

sub Run
{
    my $tid = threads->tid();
    my $log = {};
    $log->{"[$$:$tid]:00"} = "started";
    my $pid = fork();
    if ($pid == 0)
    {
         print "In child ($$): started\n";
         sleep 3;
         print "In child ($$): finished\n";
#         system("kill -9 $$");  -- brutal way
         exit 0;
    }
    waitpid($pid, 0);
    my $exitCode = $? >> 8;
    $log->{"[$$:$tid]:01"} = "finished, code=$exitCode";
    return $log;
}

my @threads = ();
foreach (1..2)
{
    push @threads, threads->new(sub { return Run() });
}
print Dumper($_->join()) for @threads;

标签: multithreadingperlfork

解决方案


在我的 Linux 机器上,使用_exitfrom POSIX而不是exit有效。不过,此解决方案可能无法移植到其他平台。

链接的文档说:

请注意,当在 Linux 中使用线程时,这不是退出线程的好方法,因为在 Linux 中进程和线程是一回事(注意:虽然这是 2003 年初的情况,但正在进行的项目中有线程Linux 中的更多 POSIXly 语义)。如果您不想从线程返回,请分离线程。

同样,perlthrtut - Perl 线程教程

考虑混合 fork() 和线程?请躺下,等到感觉过去。请注意,fork() 的语义因平台而异。例如,一些 Unix 系统将所有当前线程复制到子进程中,而其他系统只复制调用 fork() 的线程。你被警告了!


推荐阅读