【问题标题】:How to run concurrent threads in perl?如何在 perl 中运行并发线程?
【发布时间】:2014-01-31 17:36:06
【问题描述】:

以下似乎并没有像我预期的那样在并发线程中运行,而是每个进程都会阻塞,直到它完成:

my @arr = (1,2,3,4);
foreach (@arr) {
   threads->new(\&doSomething, $_)->join;
}

sub doSomething {
    my $thread = shift;
    print "thread $thread\n";
    sleep(5);
}

换句话说,它的执行似乎与非线程版本相同:

my @arr = (1,2,3,4);
foreach (@arr) {
   doSomething($_);
}

我正在运行 ActivePerl v5.10.1 mswin32-x86-multi-thread

如何在 perl 中运行并发线程?

【问题讨论】:

    标签: perl multithreading


    【解决方案1】:

    perldoc threads

    问题是在线程上调用join() 会等待它完成。您想产生线程然后加入,而不是作为一个操作产生/加入。

    再看perldoc threads 说:

    线程->list()

    threads->list(threads::all)

    threads->list(threads::running)

    threads->list(threads::joinable)

    没有参数(或使用 threads::all ) 在列表上下文中,返回一个列表 所有非连接,非分离的 线程对象。在标量上下文中, 返回相同的计数。

    使用真参数(使用线程::运行), 返回所有未加入的列表, 非分离线程对象是 仍在运行。

    使用 false 参数(使用 threads::joinable ),返回已完成运行的所有未加入、未分离的线程对象的列表(即 ->join() 不会阻塞) .

    您可以使用它来循环和列出线程,在可能的情况下加入,直到所有线程都完成(并且您可能需要一个上限来等待您将杀死它们并中止的时间)

    【讨论】:

    • 我已经尝试过了 - 只是一次生成,然后遍历线程并加入,但是一旦调用第一个加入,它就会阻塞。就好像我需要在每个线程完成之前让步,然后加入,但我不太确定该怎么做
    • 没错。 join 是一个阻塞操作。但是当主进程等待join 返回时,已经产生的线程将继续运行。在这种情况下,如果您生成所有线程然后加入,您预计第一次加入调用大约需要 5 秒,而所有其他加入调用都非常短。
    • 标记为答案。 list() 结合 is_joinable 是我需要的 - 谢谢
    【解决方案2】:

    您必须在之后加入,而不是在创建它们时加入:

    my @arr = (1,2,3,4);
    my @threads;
    foreach (@arr) {
       push @threads, threads->new(\&doSomething, $_);
    }
    foreach (@threads) {
       $_->join();
    }
    

    【讨论】:

      【解决方案3】:

      join(不仅在 Perl 中)导致调用线程等待另一个线程完成。因此,您的示例生成线程,等待它完成,然后生成另一个线程,因此您得到的印象是根本没有生成线程。

      【讨论】:

      • 那我该怎么做呢?
      【解决方案4】:

      如果你不关心线程产生的输出,你可以在线程上使用->detach()。

      我的@arr = (1,2,3,4); 我的@threads; foreach (@arr) {
      我的 $t = 线程->new(\&doSomething, $_); $t->分离(); }

      线程完成后,它会被回收,您不需要对其调用 join()。

      这个模型很适合创建工蜂,你不需要向你报告。

      【讨论】:

        【解决方案5】:

        你必须调用join 产生所有线程:

        perl -mthreads -le'$_->join for map threads->new(sub{print"Thread $_";sleep(2)}),1..4'
        

        【讨论】:

          【解决方案6】:
          my @arr = (1,2,3,4);
          my @threads;
          foreach (@arr) {
             push @threads, threads->new(\&doSomething, $_);
          }
          foreach (@threads) {
             $_->join();
          }
          

          上面的代码在小范围内工作。但是,如果您有数十个或更多线程,您的操作系统就会开始停滞。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-04-12
            • 1970-01-01
            • 1970-01-01
            • 2020-10-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多