gpt4 book ai didi

multithreading - perl 线程自分离

转载 作者:行者123 更新时间:2023-12-03 22:41:08 25 4
gpt4 key购买 nike

我对 perl(以及编程)还很陌生,过去几周一直在玩线程,到目前为止,我知道不鼓励使用它们来执行一些类似的并行任务 - 如果你的内存消耗是无法控制的线程的数量取决于一些输入值,并且简单地限制该数量并进行一些临时连接似乎非常愚蠢。所以我试图欺骗线程通过队列返回一些值,然后分离这些线程(并且没有实际加入它们) - 这是一个并行 ping 的示例:

#!/usr/bin/perl
#

use strict;
use warnings;
use threads;
use NetAddr::IP;
use Net::Ping;
use Thread::Queue;
use Thread::Semaphore;
########## get my IPs from CIDR-notation #############
my @ips;
for my $cidr (@ARGV) {
my $n = NetAddr::IP->new($cidr);
foreach ( @{ $n->hostenumref } ) {
push @ips, ( split( '/', $_ ) )[0];
}
}

my $ping = Net::Ping->new("icmp");
my $pq = Thread::Queue->new( @ips, undef ); # ping-worker-queue
my $rq = Thread::Queue->new(); # response queue
my $semaphore = Thread::Semaphore->new(100); # I hoped this may be usefull to limit # of concurrent threads

while ( my $phost = $pq->dequeue() ) {
$semaphore->down();
threads->create( { 'stack_size' => 32 * 4096 }, \&ping_th, $phost );
}

sub ping_th {
$rq->enqueue( $_[0] ) if $ping->ping( $_[0], 1 );
$semaphore->up();
threads->detach();
}

$rq->enqueue(undef);

while ( my $alive_ip = $rq->dequeue() ) {
print $alive_ip, "\n";
}

我找不到关于threads->detach() 应该如何在线程子例程中工作的完整描述,并认为这可能会起作用......而且确实如此 - 如果我在主程序(线程) 延长了它的生命周期( sleep 很好),所以所有分离的线程都完成并将它们的部分排入我的 $rq,否则它会运行一些线程将它们的结果收集到队列并退出,并发出如下警告:

Perl exited with active threads:
5 running and unjoined
0 finished and unjoined
0 running and detached

让主程序“休眠”一段时间,再一次,看起来很傻 - 有没有办法让线程只在实际的线程 -> detach() 调用之后才完成它们的工作并分离?到目前为止,我的猜测是,一旦创建线程,子内的线程->分离()就会应用,所以这不是方法。我用 CentOS 的老版本 v5.10.1 试了一下。这是否应该随着现代 v5.16 或 v5.18(使用线程编译)而改变?

最佳答案

分离线程并不是特别有用,因为您实际上是在说“我不在乎它们何时退出”。

这通常不是您想要的 - 您的进程正在完成,线程仍在运行。

一般来说 - 创建线程有开销,因为您的进程是在内存中克隆的。你想避免这样做。 Thread::Queue 也很好用,因为它是一种线程安全的信息传输方式。在您的代码中,$pq 实际上并不需要它,因为您实际上并没有在使用它的地方进行线程化。

您的信号量是一种方法,但我可以建议作为替代方法吗:

#!/usr/bin/perl
use strict;
use warnings;
use Thread::Queue;

my $nthreads = 100;

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

sub ping_host {
my $pinger = Net::Ping->new("icmp");
while ( my $hostname = $ping_q -> dequeue() ) {
if ( $pinger -> ping ( $hostname, 1 ) ) {
$result_q -> enqueue ( $hostname );
}
}
}

#start the threads

for ( 1..$nthreads ) {
threads -> create ( \&ping_host );
}

#queue the workload
$ping_q -> enqueue ( @ip_list );

#close the queue, so '$ping_q -> dequeue' returns undef, breaking the while loop.

$ping_q -> end();

#wait for pingers to finish.
foreach my $thr ( threads -> list() ) {
$thr -> join();
}
$results_q -> end();

#collate results
while ( my $successful_host = $results_q -> dequeue_nb() ) {
print $successful_host, "\n";
}

通过这种方式,您可以预先生成线程、对目标进行排队,然后在完成后整理结果。您不会因重复重生线程而产生开销,并且您的程序将等待所有线程完成。这可能需要一段时间,因为“关闭”主机上的 ping 超时将是相当长的一段时间。

关于multithreading - perl 线程自分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26629620/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com