如何在mod_perl上使用线程/多线程

时间:2016-07-27 09:05:43

标签: multithreading perl mod-perl mod-perl2

下面的代码在mod_cgi上工作正常但在mod_perl上没有。代码在创建第一个线程时崩溃。关于如何在mod_perl上实现线程的任何想法?真的有可能吗?我错过了什么?

use strict;
use warnings;
use threads;

print "Content-type: text/html\n\n";

sub testthread{
   my $value = shift;
   print "<br>test - $value"
}

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

exit;

没有给出错误消息。我的网页/脚本停止并将此错误提供给浏览器: www.abcd.com页面无效 www.abcd.com没有发送任何数据。 奇怪的是,如果我通过命令行执行脚本,它可以正常工作。

1 个答案:

答案 0 :(得分:1)

  

所以线程真的不适用于mod_perl?

我没有调查线程是否有效或不适用于mod_perl2。请记住,mod_perl的意思是在Apache进程中运行一组持久的Perl解释器。

还要记住,Apache可以杀死响应时间太长的CGI脚本。现在,添加一组线程,你的CGI脚本随时都可以在Apache内的一些持久Perl进程中进行管理,我希望很容易理解为什么人们的第一反应是&#34 ;好主意!&#34;对于我在CGI编程中遇到的任何问题,我永远不会想到这一点。

您可能或可能无法做的事情可能在很大程度上取决于您选择的MPM以及您正在使用的httpdperl编译等。

你需要解释为什么你认为你需要线程。您试图解决的问题是什么,以及CGI script run under mod_perl中使用线程将如何帮助您解决问题?

请参阅mod_perl documentation

  

线程支持

     

为了适应Apache 2.0线程架构(对于线程MPM),mod_perl 2.0需要使用线程安全的Perl解释器,也称为&#34; ithreads&#34; (口译员线程)。可以在编译时启用此机制,并确保每个Perl解释器使用其私有PerlInterpreter结构来存储其符号表,堆栈和其他Perl运行时机制。当使用此分离时,同一进程中的任意数量的线程都可以安全地执行并发回调到Perl中。这当然要求每个线程都有自己的PerlInterpreter对象,或者至少每个实例只能在任何给定时间由一个线程访问。

     

第一个mod_perl代只有一个PerlInterpreter,它由父进程构造,然后通过forx继承到子进程。 mod_perl 2.0具有可配置数量的PerlInterpreter和两类解释器,父类和克隆类。父类似于mod_perl 1.0中的父类,其中在启动时创建的主解释器编译任何预加载的Perl代码。使用Perl API perl_clone()函数从父级创建克隆。在请求时,父解释器仅用于制作更多克隆,因为克隆是实际处理请求的解释器。 Perl注意只复制可变数据,这意味着不需要运行时锁定,并且从父级共享语法树之类的只读数据,这样可以减少整个mod_perl内存占用。

     

默认情况下,mod_perl不是创建每个线程的PerlInterpreter,而是创建一个解释器池。池机制有助于大量减少内存使用。如前所述,语法树在所有克隆的解释器之间共享。如果您的服务器提供的请求超过mod_perl,那么PerlInterpreter的数量少于线程数将明显减少内存使用量。最后,也许最大的胜利是内存重用:当调用Perl子程序时,内存分配是在第一次使用它们时为变量做出的。随后使用变量可以分配更多的内存,例如如果标量变量需要保存比之前更长的字符串,或者数组中添加了新元素。作为优化,Perl会挂起这些分配,即使它们的值超出了范围&#34;。 mod_perl 2.0可以更好地控制PerlInterpreters用于传入请求。解释器存储在两个链表中,一个用于可用的解释器,另一个用于忙碌的解释器。当需要处理请求时,从可用列表的头部获取一个解释器,并在完成时将其放回到同一列表的头部。这意味着,例如,如果您有10个解释器配置为在启动时克隆,但不会同时使用不超过5个,那么这5个继续重用Perl的分配,而其他5个仍然小得多,但准备好如果有需要就去。

     

可以使用threads mode specific directives配置池的各种属性。

     

解释器池机制已被抽象为一个名为&#34; tipool&#34;,Thread Item Pool的API。此池可用于管理任何数据结构,您希望其中的数字小于配置的线程数。例如,基于tipool替换Apache::DBI将允许在同一进程的多个线程之间重用数据库连接。

     

线程环境问题

     

虽然mod_perl本身是线程安全的,但您可能会遇到代码线程安全问题。有关更多信息,请参阅Threads Coding Issues Under mod_perl

     

另一个问题是&#34;全球&#34;变量只对创建它们的解释器是全局的。可以在同一进程中运行的多个线程之间共享变量。有关详细信息,请参阅:Shared Variables