Perl如何修改shared_clone生成的共享结构,解决共享标量报错问题
报错根源
threads::shared对共享数据结构有强制要求:所有存储在共享容器内的引用类型,本身必须是共享结构。你直接执行$a1->{scalar}{10} = 1时,Perl会隐式创建一个非共享的匿名哈希作为$a1->{scalar}的取值,不符合共享结构规则,因此抛出无效值错误。
修复方法
新增嵌套字段时,先显式为对应的键赋值共享的引用结构,再操作子字段即可,修改job_to_parallelize子过程的对应逻辑:
- 首次给
$a1->{scalar}赋值时,用shared_clone创建共享的匿名哈希 - 后续操作嵌套字段就可以正常读写
修复后完整代码:
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}++; # 先给scalar键赋值共享的匿名哈希,再操作子字段 $a1->{scalar} = shared_clone({}) unless exists $a1->{scalar}; $a1->{scalar}{10} = 1; } } print Dumper($a1c); print Dumper($b1c);
补充说明
- 所有嵌套在共享结构里的数组、哈希都需要用
shared_clone或者share函数处理后再赋值,否则都会触发同类报错 - 你已经加了全局锁的逻辑,不会出现多线程同时初始化
$a1->{scalar}的冲突问题,不需要额外加其他判断逻辑
内容的提问来源于stack exchange,提问作者urie
相关产品推荐
相关产品推荐

