使用 shared_clone 可以共享复杂的数据结构。在将数据结构的组件添加到中之前,需要对其进行克隆。
use strict;
use feature 'say';
use Data::Dump qw(dd);
use threads;
use threads::shared;
my $cds = {
k1 => shared_clone( { k1_l2 => [ 1..2 ] } ),
k2 => shared_clone( { k2_l2 => [10..11] } )
};
my @threads = map { async(\&proc_ds, $cds->{$_}) } keys %$cds;
$_->join() for @threads;
dd $cds;
sub proc_ds {
my ($ds) = @_;
lock $ds;
push @{$ds->{$_}}, 10+threads->tid for keys %$ds;
}
请注意,在处理共享值时,不要允许自动创建未共享(且为空)的组件。需要明确检查其是否存在。
准备好的数据结构需要进行克隆和共享。
my $cds = { k => [ 5..7 ] }; # already built, need be shared
my $cds_share = shared_clone( $cds );
my @threads = map { async(\&proc_ds, $cds_share) } 1..3;
$_->join() for @threads;
使用与上面相同的
proc_ds()
,这将打印结构体(缩略输出):
{ 'k' => [ '5', '6', '7', '11', '12', '13' ] };
当数据结构被填充以进行共享时,就像第一个示例一样,那么需要支付的开销就会更少。否则就会涉及到数据复制,就像第二个示例中一样,是否可以接受取决于细节(数据大小、复制频率等)。
序列化数据的想法也是可行的,但它的适用性再次取决于细节,因为在这种情况下,你不仅要复制数据,还要访问磁盘。
在这种情况下,JSON肯定是一个很好的选择,因为它是一个简单易读的数据格式,也可以在工具之间共享。Storable是二进制的,直接处理Perl数据结构,并且应该很快(在处理大型数据时应该表现出来)。
另一个选项是使用worker模型并通过消息队列传递数据。然后你可以使用
Thread::Queue,或者可能利用
Thread::Queue::Any进行通信。