2014-09-19 2 views
1

У меня есть модуль, который запускает несколько потоков и нажимает их на список потоков.Можно ли повторно использовать связанные темы в perl?

например:

#!/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 и вместо устранения старых потоков и создание новых, поток иды просто держать приращением. Я слышал, что если вы не избавитесь от старых потоков в Perl, это приведет к утечке памяти и замедлит вашу программу, это правда? Являются ли данные из моих старых потоков просто сидящими в памяти занимающими пространство?

Если это может стать большой проблемой, так как мой скрипт будет частью гораздо более крупной программы, которая может генерировать сотни или тысячи потоков, все из которых будут занимать память даже после того, как они будут использованы. Как я могу остановить это? Могут ли мои потоки повторно использоваться?

Вот пример скрипта, который вызовет модуль и покажет, как потоки будут продолжать увеличиваться, даже если я присоединился к старым потокам (я думал, что «присоединиться» к тому, как вы их очистили, я что-то не так ?) Как будет использоваться этот скрипт, я не могу позволить себе иметь память из старых потоков, сидящих там, занимая пространство.

например:

#!/usr/bin/perl 

#testing.pl 

use strict; 
use warnings; 
use test_module; 

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

system 'pause'; 

Спасибо!

+0

Почему вы хотите, чтобы идентификаторы потоков были повторно использованы? –

+1

Я думаю, что мне действительно интересно, если все потоки памяти действительно выпущены после «присоединения». Тот факт, что идентификаторы продолжают увеличиваться, кажется, что старые потоки все еще существуют как-то в памяти, даже если они уже «соединены». – tjwrona1992

+4

Приращение идентификатора нити - это такая же красная селедка, как и увеличение идентификатора процесса. Ни то, ни другое не означает, что происходит истощение. – Sobrique

ответ

3

Не беспокойтесь о приращениях идентификаторов потоков - это не означает, что число работающих потоков увеличивается. После того, как поток равен join ed, он завершил выполнение и был завершен.

Однако непрерывная регенерация нитей также не идеальна - создание нити не является особенно легким в 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() - это собственный системный вызов в системах Unix, поэтому он лучше оптимизирован.

+0

Я в основном создал свою собственную очередь, но я буду изучать этот модуль, поскольку это может упростить ситуацию. – tjwrona1992

+0

У него встроенная встроенная семантика, что делает ее более аккуратной. Не обязательно более эффективный ум, но четкий код имеет свою собственную добродетель. В частности, мне нравится опция 'end()', потому что тогда цикл 'while' внутри sub вернет' undef' и выйдет. – Sobrique

Смежные вопросы