Multithreading 从线程访问包变量

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

我在从线程访问包变量时遇到问题。这是一个大项目,所以我将尝试提取代码的相关部分

我将线程模块和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'

我在想,用我们的声明声明$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并协调访问。然而,考虑到你给我们看的小片段,我同意西南努尔的观点,重新设计可能是最好的。

我现在明白我的问题有多傻了。。。谢谢你的精彩表演!我现在明白我的问题有多傻了。。。谢谢你的精彩表演!