正在关注this问题,我面临以下问题:
当我想在几个线程中循环某些哈希值并更新它们时,出现以下错误:
Thread .. terminated abnormally: Invalid value for shared scalar at ...
这是代码:
use feature qw(say);
use strict;
use warnings;
use threads ;
use threads::shared ;
use 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:shared;
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) = @_;
{
lock $lockvar;
$a1->{a}++;
$b1->{d}++;
$a1->{scalar}{10} = 1;
}
}
print Dumper($a1c);
print Dumper($b1c);
据我了解,这是因为“标量”在我克隆之前并不存在。 知道如何解决这个问题吗? (即允许我在克隆结构上声明内部线程)。
最佳答案
问题是 $a1->{scalar}{10} = 1
创建了一个新的哈希值,该哈希值存储在 $a1->{scalar}
中,并且有一个键 (10
),其值为 1
。这个新的哈希值不被共享(你从未共享过它),因此出现了问题。要解决此问题,您需要共享这个新哈希。例如:
$a1->{scalar} //= shared_clone {} ;
$a1->{scalar}{10} = 1;
也可以写成:
($a1->{scalar} //= shared_clone {} )->{10} = 1;
我认识到这有点乏味,尤其是当您有大量数据要共享时。如果您不从不同线程更新相同的 key ,那么您可以在线程内创建任意复杂的哈希值,并在最后共享它们。例如,
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
.
关于multithreading - Perl:如何编辑shared_clone的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68907848/