从线程访问包变量

时间:2013-08-20 16:16:26

标签: multithreading perl signals

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

我正在使用线程模块和 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可以从整个包中看到它。

关于发生了什么的任何想法?

2 个答案:

答案 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认为重新设计可能是最好的。