Perl线程共享数据

时间:2013-06-03 21:55:09

标签: multithreading perl shared

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

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

1 个答案:

答案 0 :(得分:3)

(我将“caller”命名为填充@ThreadInput并使用@ThreadOutput的线程。)

除非标有:shared,否则不会在线程之间共享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;
}