2012-10-11 177 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