2013-06-03 158 views
2

在我的脚本中有n个工作线程(0,1..n-1),每个工作在以下数组的第N个项目上。输入数组用于向线程提供输入,输出数组接受线程的输出。线程不会访问数组的其他项目。在那种情况下,我应该声明数组是共享的吗?Perl线程共享数据

my @ThreadInput :shared=(); 
my @ThreadOutput :shared=(); 
+0

如果数据不共享,每个线程都在一个单独的*拷贝操作*。这可能对于输入是可以的,但对于输出来说似乎不是一个好的解决方案。 – amon

回答

3

,除非标有:shared(我的名字“主叫方”用于填充@ThreadInput和消耗@ThreadOutput线程)。

Perl的变量不是线程之间共享。每个线程获得副本未标记为:shared的变量。

所以,

如果呼叫者填充@ThreadInput工人开始之前,@ThreadInput并不需要共享,但它会避免每个工人创建数组的一个副本,如果它是。

如果在工作人员启动后呼叫者填充@ThreadInput,则必须共享@ThreadInput。如果不是,呼叫者的@ThreadInput中的更改不会影响工作人员的副本。

@ThreadOutput必须共享。如果不是,工作人员@ThreadOutput中的更改不会影响呼叫者的副本。


这将是非常困难的重复使用该模型的工人。你或许应该用更多的东西像下面这样:

use threads; 
use Thread::Queue 1.03; # or Thread::Queue::Any 

use constant NUM_WORKERS => ...; 

sub handle_request { 
    my ($request) = @_; 
    return ...response...; 
} 

{ 
    my $request_q = Thread::Queue->new(); 
    my $response_q = Thread::Queue->new(); 

    my @threads; 
    my $threads; 
    for (1..NUM_WORKERS) { 
     ++$threads; 
     push @threads, async { 
     while (my $request = $request_q->dequeue()) { 
      $response_q->enqueue([ $request => handle_request($request) ]); 
     } 

     $response_q->enqueue(undef); 
     }; 
    } 

    ... Add stuff to queue $request_q->enqueue(...) ... 

    $request_q->end(); # Can be done later if you want to add more items later. 

    while ($threads && my $job = $response_q->dequeue()) { 
     if (!defined($job)) { 
     --$threads; 
     next; 
     } 

     my ($request, $response) = @$job; 
     ... handle response ... 
    } 

    $_->join for @threads; 
} 
+0

加入我的回答。 – ikegami