Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何在perl中处理多个变成僵尸的线程_Multithreading_Perl - Fatal编程技术网

Multithreading 如何在perl中处理多个变成僵尸的线程

Multithreading 如何在perl中处理多个变成僵尸的线程,multithreading,perl,Multithreading,Perl,在线程中使用管道可能会导致线程变成僵尸。事实上,管道中的命令变成了僵尸,而不是线程。这种情况并不经常发生,这很烦人,因为很难找出真正的问题。如何处理这个问题?这是什么原因造成的?这和管道有关吗?如何避免这种情况 以下是创建示例文件的代码 #buildTest.pl use strict; use warnings; sub generateChrs{ my ($outfile, $num, $range)=@_; open OUTPUT, "|gzip>$outfile"

在线程中使用管道可能会导致线程变成僵尸。事实上,管道中的命令变成了僵尸,而不是线程。这种情况并不经常发生,这很烦人,因为很难找出真正的问题。如何处理这个问题?这是什么原因造成的?这和管道有关吗?如何避免这种情况

以下是创建示例文件的代码

#buildTest.pl
use strict;
use warnings;

sub generateChrs{
    my ($outfile, $num, $range)=@_;
    open OUTPUT, "|gzip>$outfile";
    my @set=('A','T','C','G');
    my $cnt=0;
    while ($cnt<$num) {
        # body...
        my $pos=int(rand($range));
        my $str = join '' => map $set[rand @set], 1 .. rand(200)+1;
        print OUTPUT "$cnt\t$pos\t$str\n";
        $cnt++
    }
    close OUTPUT;
}

sub new_chr{
    my @chrs=1..22;
    push @chrs,("X","Y","M", "Other");
    return @chrs;
}

for my $chr (&new_chr){
    generateChrs("$chr.gz",50000,100000)
}
#buildTest.pl
严格使用;
使用警告;
次级发电机{
我的($outfile,$num,$range)=@;
打开输出“| gzip>$outfile”;
my@set=('A','T','C','G');
我的$cnt=0;
而($cnt-map$set[rand@set],1..rand(200)+1;
打印输出“$cnt\t$pos\t$str\n”;
$cnt++
}
闭合输出;
}
亚新{
my@chrs=1..22;
按@chrs、(“X”、“Y”、“M”、“其他”);
返回@chrs;
}
对于我的$chr(&new_chr){
发电商($chr.gz),50000100000)
}
以下代码偶尔会创建僵尸线程。原因或触发器未知

#paralRM.pl
use strict;
use threads;
use Thread::Semaphore;
my $s = Thread::Semaphore->new(10);

sub rmDup{
    my $reads_chr=$_[0];
    print "remove duplication $reads_chr START TIME: ",`date`;
    return 0 if(!-s $reads_chr);

    my $dup_removed_file=$reads_chr . ".rm.gz";
    $s->down();
    open READCHR, "gunzip -c $reads_chr |sort -n -k2 |" or die "Error: cannot open $reads_chr";
    open OUTPUT, "|sort -k4 -n|gzip>$dup_removed_file";

    my ($last_id, $last_pos, $last_reads)=split('\t',<READCHR>);
    chomp($last_reads);
    my $last_length=length($last_reads);
    my $removalCnts=0;

    while (<READCHR>) {
        chomp;
        my @line=split('\t',$_);
        my ($id, $pos, $reads)=@line;
        my $cur_length=length($reads);
        if($last_pos==$pos){
            #may dup
            if($cur_length>$last_length){
                ($last_id, $last_pos, $last_reads)=@line;
                $last_length=$cur_length;
            }
            $removalCnts++;
            next;
        }else{
            #not dup
        }
        print OUTPUT join("\t",$last_id, $last_pos, $last_reads, $last_length, "\n");
        ($last_id, $last_pos, $last_reads)=@line;
        $last_length=$cur_length;
    }

    print OUTPUT join("\t",$last_id, $last_pos, $last_reads, $last_length, "\n");
    close OUTPUT;
    close READCHR;
    $s->up();
    print "remove duplication $reads_chr END TIME: ",`date`;
    #unlink("$reads_chr")
    return $removalCnts;
}


sub parallelRMdup{
    my @chrs=@_;
    my %jobs;
    my @removedCnts;
    my @processing;

    foreach my $chr(@chrs){
        while (${$s}<=0) {
            # body...
            sleep 10;
        }
        $jobs{$chr}=async {
            return &rmDup("$chr.gz")
            }
        push @processing, $chr;
    };

    #wait for all threads finish
    foreach my $chr(@processing){
        push @removedCnts, $jobs{$chr}->join();
    }
}

sub new_chr{
    my @chrs=1..22;
    push @chrs,("X","Y","M", "Other");
    return @chrs;
}

&parallelRMdup(&new_chr);
#paralRM.pl
严格使用;
使用线程;
使用线程::信号量;
my$s=线程::信号量->新建(10);
子rmDup{
我的$reads_chr=$\u[0];
打印“删除重复$READES_chr START TIME:,`date`”;
如果(!-s$读取\u chr),则返回0;
my$dup_removed_file=$reads_chr.“.rm.gz”;
$s->down();
打开READCHR,“gunzip-c$reads|u chr | sort-n-k2 |”或die“错误:无法打开$reads|u chr”;
打开输出“| sort-k4-n | gzip>$dup_removed_file”;
我的($last_id,$last_pos,$last_reads)=拆分('\t',);
chomp($last_reads);
my$last_length=长度($last_reads);
我的$removalCnts=0;
而(){
咀嚼;
my@line=split('\t',$);
我的($id,$pos,$reads)=@line;
my$cur_length=长度($reads);
如果($last_pos==$pos){
#梅·杜普
如果($cur\u length>$last\u length){
($last_id、$last_pos、$last_reads)=@line;
$last_length=$cur_length;
}
$removalCnts++;
下一个
}否则{
#不重复
}
打印输出联接(“\t”,$last\u id,$last\u pos,$last\u reads,$last\u length,”\n“;
($last_id、$last_pos、$last_reads)=@line;
$last_length=$cur_length;
}
打印输出联接(“\t”,$last\u id,$last\u pos,$last\u reads,$last\u length,”\n“;
闭合输出;
关闭READCHR;
$s->up();
打印“删除重复$READES_chr END TIME:,`date`”;
#取消链接($reads\u chr)
返回$removalCnts;
}
次并行RMDUP{
我的@chrs=@;
我的%工作;
我的@removedCnts;
我的@处理;
foreach我的$chr(@chrs){
while(${$s}join();
}
}
亚新{
my@chrs=1..22;
按@chrs、(“X”、“Y”、“M”、“其他”);
返回@chrs;
}
&并行rmdup(和新的_chr);

正如你原创帖子上的评论所暗示的那样,这里的代码没有任何明显的错误。了解什么是
僵尸过程可能会有所帮助

具体地说,这是一个派生的进程(由您的
打开
),已退出,但父进程尚未收集其返回代码

对于短时间运行的代码,这并不重要——当主程序退出时,僵尸将“重新分配”到
init
,这将自动清理它们

对于较长时间的运行,您可以使用
waitpid
清理它们并收集返回代码

现在在这个特定的例子中——我看不出有什么具体的问题,但我想这与您如何打开文件句柄有关。像您这样打开文件句柄的缺点是,它们的作用域是全局的——当您在做一些琐碎的事情时,这通常是个坏消息

如果您将
open
调用更改为:

my $pid = open ( my $exec_fh, "|-", "executable" ); 
然后在
关闭后调用
waitpid
$pid
,僵尸就会结束。测试
waitpid
的返回,以了解哪个执行者出错(如果有),这将有助于跟踪原因


或者-set
$SIG{CHLD}=“IGNORE”
这将意味着您-有效地-告诉您的子进程“立即离开”-但如果它们死了,您将无法从它们那里获得返回代码。

您的所有线程都报告合理的开始和结束时间吗?但我看不出您的代码有任何明显的错误,可能导致线程未连接。然而,有一些错误d做法:①
async
块后是否缺少分号?② 在生成线程时不要忙着等待。也不要取消对信号量对象的引用。相反,你可以在释放信号量之前
down
信号量,但
up
在线程结束时释放信号量→ 好多了。③ 您应该以编程方式声明所有
@chr
都是唯一的,否则您将只为
$chr
加入最后一个线程。僵尸是在管道中创建的(排序、gzip等)。谢谢您的建议。我学到了很多!