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

标签 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 没有发送任何数据。
奇怪的是,如果我通过命令行执行脚本,它工作正常。

最佳答案

so threads really do not work with mod_perl?


我没有调查线程是否适用于 mod_perl2 .请记住mod_perl的要点是在 Apache 进程中运行一组持久的 Perl 解释器。
还要记住,Apache 可以杀死响应时间过长的 CGI 脚本。现在,添加一组线程,您的 CGI 脚本在 Apache 中的某个持久 Perl 进程中管理这些线程,这些线程随时可能消失,我希望很容易理解为什么人们的第一 react 是“好主意!”作为我在 CGI 编程中遇到的任何问题的解决方案,我永远不会想到这一点。
您能做什么或不能做什么很大程度上取决于您选择的 MPM 和方式 httpdperl你正在使用被编译等。
你需要解释为什么你认为你需要线程。您要解决的问题是什么,以及如何在 CGI script run under mod_perl 中使用线程会帮你解决吗?
mod_perl documentation :

Threads Support

In order to adapt to the Apache 2.0 threads architecture (for threaded MPMs), mod_perl 2.0 needs to use thread-safe Perl interpreters, also known as "ithreads" (Interpreter Threads). This mechanism can be enabled at compile time and ensures that each Perl interpreter uses its private PerlInterpreter structure for storing its symbol tables, stacks and other Perl runtime mechanisms. When this separation is engaged any number of threads in the same process can safely perform concurrent callbacks into Perl. This of course requires each thread to have its own PerlInterpreter object, or at least that each instance is only accessed by one thread at any given time.

The first mod_perl generation has only a single PerlInterpreter, which is constructed by the parent process, then inherited across the forks to child processes. mod_perl 2.0 has a configurable number of PerlInterpreters and two classes of interpreters, parent and clone. A parent is like that in mod_perl 1.0, where the main interpreter created at startup time compiles any pre-loaded Perl code. A clone is created from the parent using the Perl API perl_clone() function. At request time, parent interpreters are only used for making more clones, as the clones are the interpreters which actually handle requests. Care is taken by Perl to copy only mutable data, which means that no runtime locking is required and read-only data such as the syntax tree is shared from the parent, which should reduce the overall mod_perl memory footprint.

Rather than create a PerlInterpreter per-thread by default, mod_perl creates a pool of interpreters. The pool mechanism helps cut down memory usage a great deal. As already mentioned, the syntax tree is shared between all cloned interpreters. If your server is serving more than mod_perl requests, having a smaller number of PerlInterpreters than the number of threads will clearly cut down on memory usage. Finally and perhaps the biggest win is memory re-use: as calls are made into Perl subroutines, memory allocations are made for variables when they are used for the first time. Subsequent use of variables may allocate more memory, e.g. if a scalar variable needs to hold a longer string than it did before, or an array has new elements added. As an optimization, Perl hangs onto these allocations, even though their values "go out of scope". mod_perl 2.0 has a much better control over which PerlInterpreters are used for incoming requests. The interpreters are stored in two linked lists, one for available interpreters and another for busy ones. When needed to handle a request, one interpreter is taken from the head of the available list and put back into the head of the same list when done. This means if for example you have 10 interpreters configured to be cloned at startup time, but no more than 5 are ever used concurrently, those 5 continue to reuse Perl's allocations, while the other 5 remain much smaller, but ready to go if the need arises.

Various attributes of the pools are configurable using threads mode specific directives.

The interpreters pool mechanism has been abstracted into an API known as "tipool", Thread Item Pool. This pool can be used to manage any data structure, in which you wish to have a smaller number than the number of configured threads. For example a replacement for Apache::DBI based on the tipool will allow to reuse database connections between multiple threads of the same process.

Thread-environment Issues

While mod_perl itself is thread-safe, you may have issues with the thread-safety of your code. For more information refer to Threads Coding Issues Under mod_perl.

Another issue is that "global" variables are only global to the interpreter in which they are created. It's possible to share variables between several threads running in the same process. For more information see: Shared Variables.

关于multithreading - 如何在 mod_perl 上使用线程/多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38608488/

相关文章:

java - 如何在Android中使用on循环在onCreate()中启动多个线程而又未使用for循环启动线程(IllegalThreadStateException)?

perl - 尽管套接字是非阻塞的,但 Perl 上的 recv 阻塞

Perl - 如何更改字符串中出现的每个 $variable ";"

perl - 带有散列和可选标量参数的子例程

perl - mod_perl 缓存模块是否动态加载?

apache - 无法在 @INC 中找到模块 main 的可加载对象

java - 函数内的多线程变量访问

java - Android/Java多线程-线程直到主线程完成工作才继续

multithreading - std::call_once 和函数级静态初始化有什么区别

perl - 为什么这个 Perl 代码在不同的机器上运行时返回不同的数据类型?