繼這個問題之后,我面臨以下問題:
當我想在幾個執行緒中回圈處理一些哈希值并更新它們時,我得到了以下錯誤:
當我想在幾個執行緒中回圈處理一些哈希值并更新它們時,我得到了以下錯誤。
執行緒...例外終止。無效值for共享scalar在 ...
這是代碼:
use feature qw(say)。
use strict;
使用警告。
use threads ;
use threads::shared ;
使用 Data::Dumper qw(Dumper)。
my %h1 = (a => 1, b => 2) 。
my %h2 = (c => 3, d => 4) 。
my $a1 = \%h1;
my $b1 = \%h2;
my $a1c = shared_clone($a1);
my $b1c = shared_clone($b1);
my $lockvar:共享。
my $nthreads = 3;
for ( 1.$nthreads ) {
threads->create('job_to_parallelize', $a1c, $b1c, $lockvar ) ;
}
$_->join() for threads-> list();
sub job_to_parallelize{
my ($a1, $b1, $lockvar) = @_;
{
鎖定$lockvar。
$a1->{a} 。
$b1->{d} 。
$a1->{scalar}{10} = 1。
}
}
print Dumper($a1c);
print Dumper($b1c);
根據我的理解,這是因為在我克隆之前 "scalar "并不存在。 有什么辦法可以解決這個問題嗎?(也就是說,允許我在克隆的結構上宣告內部執行緒)。
uj5u.com熱心網友回復:
問題是,$a1->{scalar}{10}=1創建了一個新的哈希,它被存盤在$a1->{scalar},并且有一個鍵(10),其值為1。這個新的哈希值沒有被共享(你從未共享過它),因此出現了這個問題。為了解決這個問題,你需要共享這個新的哈希值。例如:
$a1->{scalar} //= shared_clone {} ;
$a1->{scalar}{10} = 1;
這也可以寫成:
($a1->{scalar} //= shared_clone {} )->{10} =1;
我承認這有點繁瑣,尤其是當你有大量的資料需要分享時。如果你不從不同的執行緒中更新同一個鍵,那么你可以在執行緒中創建一個任意復雜的哈希值,并在最后分享它們。例如,
sub job_to_parallelize {
my ($a1, $b1, $lockvar) = @_;
my %thr_data = (key1 => 'data1',
key2 => { inside => 42 })。)
$a1->{threads->tid} = shared_clone(\%thr_data)。
即使你確實在執行緒中更新了相同的鍵,你也許可以使用這種方法,并在最后重新組合哈希值,例如使用Hash::Merge.
uj5u.com熱心網友回復:
正如@Dada的回答中所解釋的,如果你試圖向哈希添加一個參考,而這個參考在你克隆哈希的時候并不存在,你需要把新的參考也標記為共享。下面是另一個例子,說明你可以如何遞回地做到這一點:
use feature qw(say)。
use strict;
使用警告。
use threads ;
use threads::shared ;
使用 Data::Dumper qw(Dumper)。
my %h1 = (a => 1, b => 2) 。
my %h2 = (c => 3, d => 4) 。
my $a1 = \%h1;
my $b1 = \%h2;
my $a1c = shared_clone($a1);
my $b1c = shared_clone($b1);
my $lockvar:共享。
my $nthreads = 3;
for ( 1.$nthreads ) {
threads->create('job_to_parallelize', $a1c, $b1c, $lockvar ) ;
}
$_->join() for threads-> list();
sub job_to_parallelize{
my ($a1, $b1, $lockvar) = @_;
{
鎖定$lockvar。
my $ref = check_exists_key($a1, 'a'/span>);
$$ref ;
$ref = check_exists_key($b1, 'd') 。
$$ref ;
$ref = check_exists_key($a1, ['scalar', '10']) 。
$$ref = 1;
}
}
sub check_exists_key {
my ($ref, $key ) = @_;
if (ref $key eq 'ARRAY') {
die "Unexpected: key array is empty" if @$key == 0;
if ( @$key == 1 ) {
$key = shift @$key。
}
else {
my $k = shift @$key。
if (exists $ref->{$k}) {
die "Will not overwrite scalar value with a reference"
if $ref->{$k} eq ''/span>;
return check_exists_key( $ref->{$k}, $key) 。
}
if ( @$key > 0) {
my %hash;
share(%hash);
$ref->{$k} = %hash;
return check_exists_key( $ref->{$k}, $key ) 。
}
}
}
if ( !exists $ref->{$key} ) {
$ref->{$key} = undef;
}
return($ref->{$key})。
}
print Dumper({a1c => $a1c}) 。
print Dumper({b1c => $b1c}) 。
輸出:
$VAR1 = {
'a1c'/span> => {
'b' => 2,
'a' => 4,
'scalar' => {
'10' => 1.
}
}
};
$VAR1 = {
'b1c' => {
'c' => 3,
'd' => 7, 'd' => 7.
}
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/311361.html
標籤:
