multithreading - Perl:如何编辑shared_clone的结构?

标签 multithreading perl clone

正在关注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/

相关文章:

android - 如何在Handler线程中做横向数据

java - 在 Java 中并行化 QuickSort 时,线程永远不会在 join() 处返回。为什么?

具有多线程的 Java 解析器

perl - 您如何阅读 CPAN 变更日志?

java - 在 java 中初始化类时,创建 Collection 到 ImmutableSortedSet 的深拷贝

javascript - 道场:如何克隆小部件?

java - java多线程回调

Perl LSB 隐写术脚本

perl hash 不从 param () 读取

git - 如何克隆本地 svn 存储库?