【问题标题】:Perl: Using Storable and Thread::Queue correctlyPerl:正确使用 Storable 和 Thread::Queue
【发布时间】:2013-07-17 13:36:49
【问题描述】:

我正在尝试使用 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)};

【问题讨论】:

  • use warnings 告诉你什么?看起来与as your previous question 的问题基本相同。
  • 我得到了同样的错误。我已经共享了我在第 52 行中引用的所有变量。还有其他需要共享的内容吗?
  • 没有时间真正阅读您的问题。你可以使用$q->enqueue(freeze($ref))$ref = thaw($q->dequeue()) 而不是乱用share。这些功能在 Storable 中。 (这正是 Thread::Queue::Any 所做的。)
  • @ikegami 谢谢。我能够使用冻结和解冻来解决我的问题。如果您发布一个,我将非常乐意接受您的回答:)

标签: multithreading perl storable


【解决方案1】:

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

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

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

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

或者,您可以使用Thread::Queue::Any,一个像 Thread::Queue 这样的模块,它可以自动序列化排队的项目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多