2012-10-11 129 views
0

一种方法是申报像哈希的各个层面:如何共享哈希散列在多线程的perl分享哈希散列

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 
...... 

脚本将被警告您停止“在某些线路共享标值无效”。那么有没有办法可以分享%计数和%{$计数{KEY1}}?假设我不知道有多少,并观察测试组列一个什么种水果和输出应该是这样的:

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

回答

1

在脚本中,你靠自动激活:哈希和数组,一旦被引用,只是弹簧的存在。这通常起作用。它不是当你use threads(autovivificated数据结构默认情况下不共享)。如果需要,我们可以简单地创建subhash。这将使您的WORK

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之前返回线程的返回值(在这种情况下,计数的增加,因为它是值的最后一条语句),并且不是的一个线程对象。

+0

谢谢!我知道它可以简化,我创建这个例子只是为了学习如何在perl中使用多线程。但在第二种解决方案中,你的意思是// =还是|| =? – lolibility

+0

@lolibility我用过'// ='。这意味着“如果未定义,则分配”。 '$ a // = $ b'与'$ a = defined $ a?'相同。 $ a:$ b'。这在古代波尔文中是不可用的。但是,'|| ='也可以。 – amon