multithreading - 使用带有 Memoize 的 ithread 时出错

标签 multithreading perl

我刚刚在 Perl 程序中引入了线程,其中一个模块正在使用 Memoize .
我收到此错误消息:

Thread 1 terminated abnormally: Anonymous function called in forbidden scalar context; faulting



如果我同时拥有线程和 Memoize,则会发生错误,但如果我删除其中一个元素,则会消失。但问题不是因为 Memoize 不是线程安全的——在我的代码中,所有的 memoization 都发生在同一个线程中。

这是 Memoize 的错误吗?有没有办法解决这个问题?否则,我将摆脱 Memoize。

这是一些用于隔离问题的示例代码:
use strict;
use warnings;
use threads;
use Thread::Semaphore;
use Memoize;

my $semaphore = Thread::Semaphore->new;

memoize('foo');
sub foo {
    return shift;
}

sub invoke_foo {
    $semaphore->down; # ensure memoization is thread-safe
    my $result = foo(@_);
    $semaphore->up;

    return $result;
}

my @threads;
foreach (1 .. 5) {
    my $t = threads->create( sub { invoke_foo($_) });
    push @threads, $t;
}
$_->join foreach @threads;

最佳答案

Memoize 将每个 memoized 函数的缓存存储在一个哈希中(而不是使用闭包)。它使用函数的地址作为该哈希的索引。

问题是函数的地址在克隆到新线程时会发生变化。 (在 print(\&foo, "\n"); 中添加 invoke_foo。)。这是内存中的一个错误。

解决方法:从线程中加载 memoised 模块。以下模拟(相关方面):

use strict;
use warnings;
use threads;
use Memoize;

sub foo {
    return shift;
}

sub invoke_foo {
    return foo(@_);
}

my @threads;
foreach (1 .. 5) {
    my $t = threads->create( sub {
        memoize('foo');
        invoke_foo($_);
    });
    push @threads, $t;
}
$_->join foreach @threads;

顺便说一下,每个线程都有自己的缓存。这也可以被认为是一个错误。

关于multithreading - 使用带有 Memoize 的 ithread 时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9045592/

相关文章:

php - 线程对象更改套接字资源 ID

c - C 程序中的 open 与 fopen(多线程)

Java线程困惑,为什么输出没有顺序?

arrays - 按偏移量索引 Perl 数组的速度

mysql - 如何在 Perl CGI 中使用持久的 MySQL 数据库连接

c++ - 如何使用 “non sequential”语义证明MT程序正确无误?

java - 带有匿名线程的 Reactor Scheduler

linux - sed 仅查找并替换特定的出现次数

perl - 如何从 Perl 中的纯文本中提取 URL?

python - 文本处理 - Python 与 Perl 的性能对比