共享散列哈希的一种方法是声明每个级别的散列,如:
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
答案 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 一个线程对象。