从线程访问包变量时遇到问题。这是一个大项目,所以我将尝试提取代码的相关部分。
我正在使用线程模块和 Moose 作为OO部分。
our $thread2;
around 'new' => sub {
[...]
threads->create( \&_thread1Func, $shared_self );
if (!$thread2) {
$thread2 = threads->create( \&_thread2Func, $shared_self );
$thread2->detach();
}
}
sub _thread1Func {
$thread2->kill('SIGUSR1');
}
sub _thread2Func {
$SIG{'USR1'} = sub { [...] };
while (1) {
sleep 5;
[...]
}
}
我收到以下错误:
Thread N terminated abnormally: Can't call method "kill" on an undefined value at XXXX.pm line n.
n
指向行$thread2->kill('SIGUSR1');
我在想,用our
声明$ thread2可以从整个包中看到它。
关于发生了什么的任何想法?
答案 0 :(得分:3)
如perldoc threads中所述:
自Perl 5.8以来,线程编程已经可以使用称为解释器线程的模型,它为每个线程提供了一个新的Perl解释器,默认情况下,不会导致线程之间共享数据或状态信息。
our
“为当前包中同名的包变量创建一个词法别名,以便在当前词法范围内使用。”
这并不意味着它会创建一个在线程之间共享的变量。为此,您需要threads::shared。但请注意:
此模块仅支持共享以下数据类型:标量和标量引用,数组和数组引用,以及哈希和散列引用。
您的代码对我来说很麻烦。如果你解释为什么要做你正在做的事情,我们或许可以提供更具体的帮助。
以下内容可能会与您的需求接近:
#!/usr/bin/env perl
use strict;
use warnings;
use threads;
use threads::shared;
my $thread2_tid :shared;
sub myfunc {
threads->create(\&_thread1Func);
if (!$thread2_tid) {
my $thread2 = threads->create(\&_thread2Func);
$thread2_tid = $thread2->tid;
}
}
sub _thread1Func {
while (1) {
next unless defined $thread2_tid;
last if $thread2_tid == -1;
my $thread2 = threads->object($thread2_tid);
$thread2->kill('SIGUSR1');
sleep 1;
}
}
sub _thread2Func {
local $SIG{'USR1'} = sub { print "SIGUSR1 received\n" };
local $| = 1;
while (1) {
sleep 1;
print '.';
if (5 < time - $^T) {
$thread2_tid = -1;
last;
}
}
}
myfunc();
$_->join for threads->list;
答案 1 :(得分:1)
默认情况下,perl变量在创建线程时跨线程复制。每个线程基本上都在自己的解释器中运行('ithreads'中的'i')。
$thread2
在范围内(感谢our
),但在_threadFunc1
创建时未定义。因此,新线程获取$thread2
的副本,也是未定义的,然后,如您所知,致命地尝试对未定义的对象进行方法调用。
您可以在创建必须引用其初始值的线程之前初始化$thread2
,或者share
并协调访问。然而,鉴于您向我们展示了一小段摘录,我同意SinanÜnür认为重新设计可能是最好的。