Multithreading 从线程访问包变量
我在从线程访问包变量时遇到问题。这是一个大项目,所以我将尝试提取代码的相关部分 我将线程模块和Moose用于OO部分Multithreading 从线程访问包变量,multithreading,perl,signals,Multithreading,Perl,Signals,我在从线程访问包变量时遇到问题。这是一个大项目,所以我将尝试提取代码的相关部分 我将线程模块和Moose用于OO部分 our $thread2; around 'new' => sub { [...] threads->create( \&_thread1Func, $shared_self ); if (!$thread2) { $thread2 = threads->create( \&_thread2Func, $shared_sel
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'
我在想,用我们的声明声明$thread2可以使它在整个包中可见
有什么想法吗?如中所述:
自Perl 5.8以来,线程编程一直使用一种称为解释器线程的模型,该模型为每个线程提供一个新的Perl解释器,默认情况下,线程之间不会共享任何数据或状态信息
为当前包中同名的包变量创建词法别名,以便在当前词法范围内使用
这并不意味着它创建了一个在线程之间共享的变量。为此,你需要。但是,请注意:
此模块仅支持共享以下数据类型:标量和标量引用、数组和数组引用以及哈希和哈希引用
我觉得你的代码很麻烦。如果你解释你为什么要做你正在做的事情,我们可能会提供更具体的帮助
以下操作可能与您想要的接近:
#!/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;
如中所述:
自Perl 5.8以来,线程编程一直使用一种称为解释器线程的模型,该模型为每个线程提供一个新的Perl解释器,默认情况下,线程之间不会共享任何数据或状态信息
为当前包中同名的包变量创建词法别名,以便在当前词法范围内使用
这并不意味着它创建了一个在线程之间共享的变量。为此,你需要。但是,请注意:
此模块仅支持共享以下数据类型:标量和标量引用、数组和数组引用以及哈希和哈希引用
我觉得你的代码很麻烦。如果你解释你为什么要做你正在做的事情,我们可能会提供更具体的帮助
以下操作可能与您想要的接近:
#!/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;
默认情况下,在创建线程时跨线程复制perl变量。每个线程基本上都在其自己的解释器中运行,即中的“i” $thread2在范围内,这要感谢我们在创建_threadFunc1时未定义的功能。因此,新线程将获得$thread2的副本(也是未定义的),然后,如您所知,致命地尝试对未定义对象进行方法调用
您可以在创建必须引用其初始化值的线程之前初始化$thread2,也可以在创建线程之前初始化$thread2并协调访问。但是,考虑到您向我们展示的小片段,我同意SinanÜnür的观点,重新设计可能是最好的。默认情况下,perl变量在创建线程时跨线程复制。每个线程基本上都在其自己的解释器中运行,即中的“i” $thread2在范围内,这要感谢我们在创建_threadFunc1时未定义的功能。因此,新线程将获得$thread2的副本(也是未定义的),然后,如您所知,致命地尝试对未定义对象进行方法调用
您可以在创建必须引用其初始化值的线程之前初始化$thread2,也可以在创建线程之前初始化$thread2并协调访问。然而,考虑到你给我们看的小片段,我同意西南努尔的观点,重新设计可能是最好的。我现在明白我的问题有多傻了。。。谢谢你的精彩表演!我现在明白我的问题有多傻了。。。谢谢你的精彩表演!