假设我有5个文件,名为 a 到 e 。我想并行处理这些。我以为我可以这样做:
my @ltrs = ('a'..'e');
for my $fnum (0..2) {
$pid = fork();
if ($pid) {
push(@childs, $pid);
}
elsif ($pid == 0) {
do {
my $ltr = shift(@ltrs);
print "Open file $ltr on $fnum\n";
} until (scalar(@ltrs)==0);
exit(0);
}
else {
die "Couldn't fork: $!\n";
}
}
foreach (@childs) {
waitpid($_, 0);
}
但每个子进程都访问@ltrs
的所有五个元素:
Open file a on 0
Open file b on 0
Open file c on 0
Open file d on 0
Open file e on 0
Open file a on 1
Open file b on 1
Open file c on 1
Open file d on 1
Open file e on 1
Open file a on 2
Open file b on 2
Open file c on 2
Open file d on 2
Open file e on 2
当一个进程shift
是数组中的一个元素时,为什么当下一个进程查看数组时该元素仍然存在?我假设在第一个shift
之后,接下来的任何进程都会找到一个以b
开头的数组,但显然我错过了一些东西。
答案 0 :(得分:7)
流程之间不共享数据。每个进程都有自己的副本。
如果您想分享,那么整个广泛的进程间通信世界对您开放。 perldoc页面perlipc告诉你所有相关信息。
如果不需要每个实例的完整进程,那么使用线程是另一种方法。与进程线程可以共享数据不同(尽管它们在Perl中默认不是这样)。 perldoc页面perlthrtut是此特定主题的起点。
答案 1 :(得分:3)
试试这个:
use Parallel::ForkManager;
my $max_processes = 3;
my $pm = Parallel::ForkManager->new($max_processes);
my @ltrs = ('a'..'e');
for my $ltr (@ltrs) {
my $pid = $pm->start and next;
print "Open file $ltr in $$\n";
sleep 1;
$pm->finish;
}
$pm->wait_all_children;
这为您排队,确保一次不超过3个孩子;但是,与您的代码不同,它会为每个字母执行单独的fork。
如果您需要将子项中的数据返回给父项,请设置run_on_finish挂钩,如https://metacpan.org/module/Parallel::ForkManager#Data-structure-retrieval所示。