我正在尝试了解Perl对线程的使用。阅读文档时,我发现了以下代码:
use threads;
my $thr = threads->create(&sub1); # Spawn the thread
$thr->detach(); # Now we officially don't care any more
sleep(15); # Let thread run for awhile
sub sub1 {
my $count = 0;
while (1) {
$count++;
print("$count is $countn");
sleep(1);
}
}
目标似乎是创建一个运行sub1 15秒的线程,同时打印一些字符串。然而,我想我不明白节目结束时发生了什么。
首先,detach()
定义如下:
一旦线程被分离,它将运行直到它完成;然后是Perl之后会自动清理。
但是,子程序什么时候结束?while(1)
永远不会结束。我也没有在sleep()
中找到任何信息,它会导致循环中断。最重要的是,从我们分离的那一点开始,我们"等待脚本完成,然后清理它"15秒,所以如果我们等待子例程完成,为什么我们在主脚本中需要sleep()
?这个职位对我来说很尴尬;这表明主程序睡眠15秒。但这有什么意义呢?主程序(线程?)在子线程保持运行的同时休眠,但子程序是如何终止的?
我想这个想法是在sleep
-ing完成后,子程序结束,之后我们可以分离/清理。但这在句法上是如何清晰的呢?在睡眠的定义中,哪里说sleep
终止了一个子例程(以及为什么),它如何知道在有多个线程的情况下终止哪一个子例程?
程序结束时,所有线程都结束。程序在主线程结束时结束。主线程中的sleep
只是使程序保持短时间运行,之后主线程(因此程序,因此所有创建的线程)也结束。
那么detach
怎么了?它只是说"我永远不会加入这个线程,我不在乎它会返回什么"。如果没有detach
线程或join
线程,程序结束时会收到警告。
detach
线程意味着"我不再在乎了",这实际上意味着当您的进程退出时,线程将出错并终止。
实际上,我认为您从来都不想在perl中分离线程,只需在代码末尾添加一个join
,这样它就可以干净地退出,并通过信号量或Thread::Queue
发出信号来终止。
$_ -> join for threads -> list;
会成功的。
在我看来,那个代码示例是个糟糕的示例。对于sleep
来说,这简直是一团糟,所以一个分离的线程有机会完成,而你只需要join
和就可以知道它已经完成了。perl
线程尤其如此,假设它们是轻量级的是欺骗性的,因此可以很容易地启动(以及detached
)。如果您的派生次数足够多,以至于join
处理它们的开销太高,那么您使用perl线程是错误的,可能应该使用fork
。
你说得很对——线程永远不会终止,所以你的代码总是有一个"脏"出口。
所以我会重写:
#!/usr/bin/perl
use strict;
use warnings;
use threads;
use threads::shared;
my $run : shared;
$run = 1;
sub sub1 {
my $count = 0;
while ($run) {
$count++;
print("$count is $countn");
sleep(1);
}
print "Terminatingn";
}
my $thr = threads->create( &sub1 ); # Spawn the thread
sleep(15); # Let thread run for awhile
$run = 0;
$thr->join;
通过这种方式,main向线程发出信号说"我完成了",并等待它完成当前循环。