Multithreading Perl:正确使用Storable和Thread::Queue

Multithreading Perl:正确使用Storable和Thread::Queue,multithreading,perl,storable,Multithreading,Perl,Storable,我试图使用Storable来帮助收集多个线程生成的数据。如果没有线程部分,代码的可存储位工作得很好。但是,使用我提供的示例代码,我得到以下错误: 线程启动失败:./storable2.pl第55行的共享标量值无效。 第55行是$hash{“Simpsons”}{“Krusty”}=\%test2\u hash @ikegami在之前的一篇文章中建议我,错误是因为我的引用指向了一个非共享变量。我尝试与代码共享变量my%test2\u hash:shared(这是示例代码的一部分),但我想我用错了

我试图使用Storable来帮助收集多个线程生成的数据。如果没有线程部分,代码的可存储位工作得很好。但是,使用我提供的示例代码,我得到以下错误:

线程启动失败:./storable2.pl第55行的共享标量值无效。

第55行是
$hash{“Simpsons”}{“Krusty”}=\%test2\u hash

@ikegami在之前的一篇文章中建议我,错误是因为我的引用指向了一个非共享变量。我尝试与代码共享变量
my%test2\u 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:(我真的试着用我现有的工具进行实验,但我又碰上了墙

更新: 我更新了代码。使用strict和warnings,我得到以下输出:

thread failed to start: Invalid value for shared scalar at ./storable2.pl line 52.

第52行是
%test2\u hash=%{retrieve($tmp\u filename)};

由于您只是为了传输而共享结构,因此可以通过序列化数据结构而不是共享它来绕过整个问题

您可以使用的
冻结
解冻
来序列化和恢复数据结构

$queue->enqueue(freeze($_)) for @sentiments;

while (my $job = $queue->dequeue()) {
    test1(thaw($job));
}

或者,您可以使用诸如Thread::Queue之类的模块,该模块自动序列化排队项目。

由于您只是为了传输而共享结构,因此您可以通过序列化数据结构而不是共享它来绕过整个问题

您可以使用的
冻结
解冻
来序列化和恢复数据结构

$queue->enqueue(freeze($_)) for @sentiments;

while (my $job = $queue->dequeue()) {
    test1(thaw($job));
}

或者,您可以使用诸如Thread::Queue之类的模块,该模块自动序列化排队的项目。

使用警告告诉您什么?
看起来实质上是同一个问题。我得到了相同的错误。我已经共享了第52行中提到的所有变量。是否还有其他需要共享的内容?没有时间重复请仔细阅读您的问题。您可以使用
$q->enqueue(freeze($ref))
$ref=saw($q->dequeue())
而不是混用
共享
。这些函数是可存储的。(这正是Thread::Queue::Any所做的。)@ikegami谢谢你。我可以使用冻结和解冻来解决我的问题。如果你发布一个答案,我将非常乐意接受你的答案:)什么是
使用警告
告诉你的?看起来实质上是同一个问题,我也有同样的错误。我已经分享了第52行中提到的所有变量。还有什么需要分享的吗?没有时间认真阅读你的问题。您可以使用
$q->enqueue(freeze($ref))
$ref=saw($q->dequeue())
而不是与
共享混为一谈。这些函数是可存储的。(这正是Thread::Queue::Any所做的。)@ikegami谢谢。我可以用冷冻和解冻来解决我的问题。如果你发布一个答案,我将非常乐意接受你的答案:)