2013-06-03 75 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