如何在多线程perl中共享散列哈希

时间:2012-10-11 20:50:38

标签: multithreading perl hash share

共享散列哈希的一种方法是声明每个级别的散列,如:

my %hash : shared;
$hash{test} = &share({});

但如果第一级密钥的数量无法预测或太多而无法宣布每个密钥,该怎么办。

如下面的代码:

#!/usr/bin/perl -w
use strict;
use threads;
use threads::shared;

my %counts :shared;
my $infile = $ARGV[0];
open my $inf, "$infile";

while(my $inline = <$inf>){
    chomp($inline);
    my @entry = split(/\t/,$inline);
    my $t = threads->create('WORK',@entry)->join;
}

foreach my $i(sort {$a cmp $b} keys %counts){
    foreach my $j(sort {$a cmp $b} keys %{$counts{$i}}){
        print "$i\t$j\t$counts{$i}{$j}\n";
    }
}

sub WORK{
    my @work = @_;
    $counts{$work[0]}{$work[1]}++;
}

测试集:

apple   pie
banana  icecream
orange  juice
mango   juice
mango   pie
mango   pie
......

将通过警告您“SOME行上共享标量的值无效”来停止脚本。那么我可以分享%计数和%{$ counts {KEY1}}吗?假设我不知道我将在测试集第一列中观察到多少和哪种水果,输出应该是这样的:

apple    pie      1
banana   icecream 1
mango    juice    1
mango    pie      2
orange   juice    1

1 个答案:

答案 0 :(得分:1)

在你的脚本中,你依赖于 autovivification :哈希和数组一旦被引用,就会出现。这通常有效。当use threads(默认情况下不共享自动生成的数据结构)时,它不会出现。如果需要,我们可以简单地创建subhash。这将使您的WORK sub

sub WORK{
  unless (exists $counts{$_[0]}) {
    my %anon :shared;
    $counts{$_[0]} = \%anon;
  }
  $counts{$_[0]}{$_[1]}++;
}

sub WORK { ($counts{$_[0]} //= do{my %a :shared; \%a})->{$_[1]}++ }

或类似的。我还删除了@_数组的无用复制。

请注意,您的示例甚至不需要线程。因为你做了

my $t = threads->create('WORK',@entry)->join;

这几乎完全等同于

my $t = WORK(@entry);

此外,join返回线程的返回值(在这种情况下,在增量之前计数,因为它是最后一个语句的值),并且 not 一个线程对象。