Perl:从并行线程派生

And*_*dyH 1 perl multithreading fork

下面的代码假定运行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;
Run Code Online (Sandbox Code Playgroud)

cho*_*oba 6

在我的Linux系统中,使用_exitPOSIX,而不是出口工程。但是,此解决方案可能无法移植到其他平台。

链接的文档说:

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

同样,perlthrtut-Perl中的线程教程

想混合fork()和线程?请躺下,等到感觉消失。请注意,fork()的语义在平台之间有所不同。例如,某些Unix系统将所有当前线程复制到子进程中,而其他系统仅复制称为fork()的线程。你被警告了!