我正在尝试使用Storable来帮助收集多个线程生成的数据。没有线程部分,可存储的代码位工作得很好。但是,使用我提供的示例代码,我收到以下错误:
thread failed to start: Invalid value for shared scalar at ./storable2.pl line 55.
第55行是$hash{"Simpsons"}{"Krusty"} = \%test2_hash;
@ikegami在之前的帖子中告诉我,错误是由于我的引用正在引用非共享变量引起的。我尝试使用代码my %test2_hash : shared;
(这是示例代码的一部分)共享变量,但我想我使用的不正确。
我还尝试创建一个共享的新哈希:
my %shared_hash;
%test2_hash = %{retrieve($tmp_filename)};
%shared_hash = share(%test2_hash);
然而,这会导致相同的错误。
这是我的示例代码:
#!/usr/bin/perl
# storable.pl
use strict;
use warnings;
use Storable qw(store retrieve);
use File::Temp;
use threads;
use threads::shared;
use Thread::Queue;
use constant NUM_WORKERS => 10;
use Data::Dumper qw(Dumper);
my @out_array;
main();
sub main
{
start_threads();
foreach my $item (@out_array) {
print "item: $item\n";
}
}
sub start_threads
{
my $queue = Thread::Queue->new();
foreach (1..NUM_WORKERS) {
async {
while (my $job = $queue->dequeue()) {
test1($job);
}
};
}
my @sentiments = ("Axe Murderer", "Mauler", "Babyface", "Dragon");
$queue->enqueue(@sentiments);
$queue->enqueue(undef) for 1..NUM_WORKERS;
$_->join() for threads->list();
my @return_array = @out_array;
return @return_array;
}
sub test1
{
my $fighter = $_[0];
my $tmp_filename : shared;
my %hash : shared;
my %test2_hash : shared;
$tmp_filename = get_temp_filename();
test2($fighter, $tmp_filename);
%test2_hash = %{retrieve($tmp_filename)};
$hash{"Simpsons"}{"Krusty"} = \%test2_hash;
push @out_array, \%test2_hash;
return;
}
sub test2
{
my ($fighter, $tmp_filename) = @_;
my %test2_hash;
$test2_hash{"Zuffa"}{"LLC"} = $fighter;
store(\%test2_hash, $tmp_filename);
}
sub get_temp_filename {
my $fh = File::Temp->new(
TEMPLATE => 'tempXXXXX',
DIR => 'tmpdir',
SUFFIX => '.tmp',
);
return $fh->filename;
}
与Thread :: Queue一起使用时,使用Storable的正确方法是什么?或者问题纯粹与不正确的Thread :: Queue实现有关吗?
抱歉@ikegami :(我真的试着尝试一下我的工具,但是我再次碰壁了。
更新: 我更新了代码。使用严格和警告我得到以下输出:
thread failed to start: Invalid value for shared scalar at ./storable2.pl line 52.
第52行是%test2_hash = %{retrieve($tmp_filename)};
答案 0 :(得分:1)
由于您只是共享结构以进行传输,因此您可以通过序列化数据结构而不是共享来绕过整个问题。
您可以使用Storable的freeze
和thaw
来序列化和恢复您的数据结构。
$queue->enqueue(freeze($_)) for @sentiments;
while (my $job = $queue->dequeue()) {
test1(thaw($job));
}
或者,您可以使用Thread::Queue::Any,一个像Thread :: Queue这样的模块,它会自动序列化排队的项目。