2013-08-20 60 views
1

我遇到問題以從線程訪問包變量。這是一個大項目,所以我會嘗試提取代碼的相關部分。從線程訪問包變量

我正在使用線程模塊和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');

我在想,宣佈$線程2與our使其成爲全包可見。

對發生了什麼有什麼想法?

回答

3

perldoc threads提到:

Since Perl 5.8, thread programming has been available using a model called interpreter threads which provides a new Perl interpreter for each thread, and, by default, results in no data or state information being shared between threads.

our「使得詞法別名同名在當前包中的當前詞法範圍內使用的包變量」。

這並不意味着它會創建一個在線程間共享的變量。爲此,您需要threads::shared。但是,請注意:

This module supports the sharing of the following data types only: scalars and scalar refs, arrays and array refs, and hashes and hash refs.

您的代碼對我來說看起來很麻煩。如果你解釋你爲什麼要做你正在做的事情,我們可能會提供更具體的幫助。

下可能會做一些接近你想要什麼:

#!/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; 
+0

我現在可以看到我的問題是愚蠢的......感謝亮點! – Titi

1

默認情況下,perl的變量是在創建線程的時間複製跨線程。每個線程本質上都運行在它自己的解釋器中('ithreads'中的'i')。

$thread2在範圍內(感謝our),但在創建_threadFunc1時未定義。因此新線程得到$thread2的副本,也是未定義的,然後,如您所知,致命地嘗試針對未定義對象的方法調用。

您可以在創建線程之前初始化$thread2,該線程必須引用其初始值或share它並協調訪問。但是,鑑於您向我們展示的小節選,我同意SinanÜÜür的重新設計可能是最好的。