Perl:在线程之间共享复杂数据结构

问题描述:

我喜欢在线程之间共享复杂数据结构。 据我所知,这是不可能的线程:共享(只有基本类型是可共享的)。Perl:在线程之间共享复杂数据结构

所以我想用JSON或Storable对序列化/反序列化结构,所以它只是一个字符串,我可以完美地共享。但是我需要在使用前将其打开并在更改后将其打包。

  • 这是一种常见的解决方法吗?

  • 有没有更好的方法?

  • 您是否更喜欢JSON或可存储或其他?

感谢您的帮助!

编辑

我只是做了一些测试与可存储和JSON。 JSON更快,生成更小的序列化字符串。我原本没想到。

+0

您可以使用'shared_clone'共享复杂的数据结构,但是您需要在将组件添加到结构之前克隆组件(无法“共享”现成的组件)。那是合适的吗? – zdim

+0

如果发生这种情况,请参阅[当某人回答我的问题时该怎么办?](http://*.com/help/someone-answers) – zdim

可以使用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' ] }; 
+0

@ chris01添加了一个可能更重要的示例 – zdim

当处理这个问题,我使用Thread::Queue来传递我的物体,并且通常使用Storable来连续化。

我还没有打扰过性能的比较,因为通常是我的数据传递开销并不是限制因素。

注 - Storable的主要优点是,它允许一些有限的对象的支持(不 - 要小心 - 它只有作品,如果你的对象包含个体经营):

#!/usr/bin/env perl 
use strict; 
use warnings; 

package MyObject; 

sub new { 
    my ($class, $id) = @_; 
    my $self = {}; 
    $self -> {id} = $id; 
    $self -> {access_count} = 0; 
    bless $self, $class; 
    return $self; 
} 

sub access_thing { 
    my ($self) = @_; 
    return $self -> {access_count}++; 
} 

sub get_id { 
    my ($self) = @_; 
    return $self -> {id}; 
} 

package main; 

use threads; 
use Thread::Queue; 

use Storable qw (freeze thaw); 

my $thread_count = 10; 

my $work_q = Thread::Queue -> new; 

sub worker { 
    while (my $item = $work_q -> dequeue) { 
     my $obj = thaw ($item); 
     print $obj -> get_id, ": ", $obj -> access_thing,"\n";  

    } 
} 

for (1..$thread_count) { 
    threads -> create (\&worker); 
} 

for my $id (0..1000) { 
    my $obj = MyObject -> new ($id); 
    $work_q -> enqueue (freeze ($obj)); 
} 

$work_q -> end; 

$_ -> join for threads -> list; 

如果JSON会限制你到数组/散列数据结构 - 这可能适合您的使用情况。