我是perl的新手,我编写了一个程序来处理一组操作系统映像上的相同操作。由于操作相同,我使用了线程。附加了该程序的缩小版本。问题是,主程序永远不会出现并等待永远。在追踪时,我看到主程序在等待" tee"命令。我有什么东西在这里搞砸了?
我在使用Perl版本5.1的CentOS 6.7上,由于许多其他依赖项,我无法继续前进:(
#!/usr/bin/perl -w
use threads;
my $tee_pid= open my $tee, "|-", "tee mylog";
my @images = ( "image1" , "image2");
foreach my $image (@images){
$_ = async { do_ops_on_image() };
sleep ( 60 );
}
while( threads->list ) {
for my $joinable ( threads->list( threads::joinable ) ) {
$joinable->join;
}
}
print "All thread completed \n";
close $tee;
sub do_ops_on_image
{
my $time = `date`;
my $id = threads->tid();
sleep (120) if ( $id ==2 );
print $tee "my $id started at $time \n";
}
答案 0 :(得分:7)
这似乎是在版本5.14.0中修复的perl中的错误。如果你真的无法安装更新的perl(除了系统perl),那么尽量避免$ tee共享文件句柄,这是导致主线程挂起的原因。
此外,等待子线程完成的代码使用一个活动的CPU循环,它会烧掉大量的CPU。如果您只想等到所有子线程都完成,请执行类似
的操作my @threads;
...
for ... {
push @threads, async { ... }
}
...
$_->join for @threads;
答案 1 :(得分:3)
我对perl [...]使用线程相对较新。
这是你的问题。
Perl线程很奇怪。他们有许多意想不到的不良行为;特别是,大多数变量不能在线程之间安全地共享,并且某些模块根本不支持在线程环境中使用。引用the threads
documentation:
Perl提供的“基于解释器的线程”并不是人们可能期望或希望的快速,轻量级的多任务处理系统。线程的实现方式使其易于滥用。很少有人知道如何正确使用它们或能够提供帮助。
官方不鼓励在perl中使用基于解释器的线程。
对于许多常见应用程序,Parallel::ForkManager
模块可能是更合适的选择。