我可以在perl中重用连接的线程吗?

时间:2014-09-19 15:32:16

标签: multithreading perl thread-safety threadpool

我有一个运行多个线程的模块,并将它们推送到线程列表中。

例如:

#!/usr/bin/perl

#test_module.pm

package test_module;

use strict;
use warnings;
use threads;

sub main {

    my $max_threads = 10;
    my @threads     = ();

    # create threads
    while (scalar @threads < $max_threads) {
        my $thread = threads->new(\&thread_sub);
        push @threads, $thread;
    }

    # join threads
    for my $thread (@threads) {
        $thread->join();
    }
}

sub thread_sub {
    my $id = threads->tid();
    print "I am in thread $id\n";
}

1;

问题是我从一个Perl脚本多次调用此模块,而不是消除旧线程并创建新线程,线程ID只是保持递增。我听说如果你没有正确摆脱Perl中的旧线程,这将导致内存泄漏并减慢程序速度,这是真的吗?来自旧线程的数据是否只是占用内存空间?

如果是这样,这可能会成为一个大问题,因为我的脚本将成为一个更大的程序的一部分,可能会生成数百或数千个线程,所有这些线程即使在完成使用后也会占用内存。我怎么能阻止这种情况发生?我的线程可以重复使用吗?

这是一个示例脚本,它将调用模块并显示线程将如何继续递增,即使我加入了旧线程(我认为“加入”是你在他们之后清理的方式,我做错了什么? )这个脚本的使用方式我不能从占用空间的旧线程中获取内存。

例如:

#!/usr/bin/perl

#testing.pl

use strict;
use warnings;
use test_module;

test_module::main();
test_module::main();
test_module::main();

system 'pause';

谢谢!

1 个答案:

答案 0 :(得分:3)

不要担心线程ID递增 - 这并不意味着正在运行的线程数正在增加。一旦线程join,它就已经完成执行并被终止。

然而,不断重新生成的线程也不理想 - 在perl中创建线程不是特别轻量级的操作。因此,如果您必须做类似的事情,并且特别关注效率 - 请转而fork()

我发现我倾向于使用{工作线程'模型,使用Thread::Queue

my $processing_q = Thread::Queue -> new();

sub worker_thread {
    while ( my $item = $processing_q -> dequeue() ) {
       # do stuff to $item
    }
}

for ( 1 .. $num_threads ) {
    my $thr = threads -> create ( \&worker_thread );
}

$processing_q -> enqueue ( @generic_list_of_things ); 
$processing_q -> end;

foreach my $thread ( threads -> list() ) {
    $thread -> join();
}

这会将一批项目输入到队列中,并且您的工作线程将一次处理一个项目 - 这意味着您可以运行合理的数字,而无需不断重新生成。

作为替代方案 - 看看Parallel::ForkManager - fork样式并行处理最初可能看起来违反直觉,但fork()是Unix系统上的本机系统调用,因此它往往更好地进行优化。