2

假设我有 5 个文件,名为ae。我想并行处理这些。我以为我可以做这样的事情:

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,但显然我错过了一些东西。

4

2 回答 2

7

数据不在进程之间共享。每个进程都有自己的副本。

如果您想分享,那么整个进程间通信的广阔世界对您开放。perldoc 页面perlipc会告诉您所有相关信息。

如果不需要每个实例的完整进程,那么使用线程是另一种方法。与进程不同,线程可以共享数据(尽管在 Perl 中它们默认不共享)。perldoc 页面perlthrtut是这个特定主题的起点。

于 2012-11-21T16:32:28.843 回答
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 个;但是,与您的代码不同,它确实为每个字母做了一个单独的分叉。

如果您需要将数据从子级返回给父级,请设置一个 run_on_finish 挂钩,如https://metacpan.org/module/Parallel::ForkManager#Data-structure-retrieval所示。

于 2012-11-21T19:39:48.593 回答