本文首先概述了Perl线程的概念和意义,接着回顾了Perl语言中对Perl线程支持的演化历史,然后通过一系列示例重点介绍了Perl中Perl线程的实现,数据的共享以及Perl线程间的同步,最后归纳并总结了全文主要内容。
Perl线程概述
Perl线程是一个单一的执行流程,它是所有程序执行过程中最小的控制单位,即能被CPU所调度的最小任务单元。Perl线程与进程之间既有联系,又完全不同。简单地说,一个Perl线程必然属于某一个进程,而一个进程包含至少一个或者多个Perl线程。早期的计算机系统一次只能运行一个程序,因此,当有多个程序需要执行的时候,唯一的办法就是让它们排成队,按顺序串行执行。进程的出现打破了这种格局,CPU资源按时间片被分割开来,分配给不同的进程使用。这样一来,从微观上看进程的执行虽然仍是串行的,但是从宏观上看,不同的程序已经是在并行执行了。如果我们把同样的思想运用到进程上,很自然地就会把进程再细分成更小的执行单位,即Perl线程。由于一个进程又往往需要同时执行多个类似的任务,因此这些被细分的Perl线程之间可以共享相同的代码段,数据段和文件句柄等资源。有了进程,我们可以在一台单CPU计算机系统上同时运行Firefox和MicrosoftOfficeWord等多个程序;有了Perl线程,我们可以使Firefox在不同的标签里同时加载多个不同的页面,在OfficeWord里编辑文档的同时进行语法错误检查。因此,Perl线程给我们带来了更高的CPU利用率、更快速的程序响应、更经济地资源使用方式和对多CPU的体系结构更良好的适应性。
Perl线程的历史
5005threadsPerl线程模型
Perl对Perl线程的支持最早可以追溯到1998年7月发布的Perlv5.005。其发布申明指出,Perlv5.005中加入了对操作系统级Perl线程的支持,这个新特性是一个实验性的产品,这也就是我们现在所称的5005threadsPerl线程模型。对于5005threadsPerl线程模型来说,默认情况下,所有数据结构都是共享的,所以用户必须负责这些共享数据结构的同步访问。如今5005threads已经不再被推荐实用,Perlv5.10以后的版本里,也将不会再支持5005threadsPerl线程模型。
ithreadsPerl线程模型
2000年5月发布的Perlv5.6.0中开始引入了一个全新的Perl线程模型,即interpreterthreads,或称为ithreads,也正是在这个版本的发布申明中第一次提出了5005threadsPerl线程模型将来可能会被禁用的问题。尽管如此,ithreads在那个时候还是一个新的实验性的Perl线程模型,用户并不能直接使用它,唯一的办法是通过fork函数模拟。经过两年时间的发展,到2002年7月,Perlv5.8.0正式发布,这时ithreads已经是一个相对成熟的Perl线程模型,发布申明中也鼓励用户从老的5005threadsPerl线程模型转换到新的ithreadsPerl线程模型,并明确指出5005threadsPerl线程模型最终将被淘汰。本文后面所讨论的所有内容也都是基于新的ithreadsPerl线程模型。在ithreadsPerl线程模型中,最与众不同的特点就在于默认情况一下一切数据结构都不是共享的,这一点我们会在后面内容中有更深刻的体会。
现有环境支持哪种Perl线程模型
既然Perl中有可能存在两种不同的Perl线程模型,我们很自然地就需要判断现有Perl环境到底支持的是哪一种Perl线程实现方式。归纳起来,我们有两种方法:
在shell里,我们可以通过执行perl–V|grepusethreads命令来获取当前Perl线程模型的相关信息,例如
清单1.shell中查询Perl当前Perl线程模型
- >perl-V|grepuse.*threads
- config_args='-des-Doptimize=-O2-g-pipe-m32-march=i386-mtune=pentium4-Dversion=5.8.5
- -Dmyhostname=localhost-Dperladmin=root@localhost-Dcc=gcc-Dcf_by=RedHat,Inc.
- -Dinstallprefix=/usr-Dprefix=/usr-Darchname=i386-linux-Dvendorprefix=/usr
- -Dsiteprefix=/usr-Duseshrplib-Dusethreads-Duseithreads-Duselargefiles-Dd_dosuid
- -Dd_semctl_semun-Di_db-Ui_ndbm-Di_gdbm-Di_shadow-Di_syslog-Dman3ext=3pm-Duseperlio
- -Dinstallusrbinperl-Ubincompat5005-Uversiononly-Dpager=/usr/bin/less-isr
- -Dinc_version_list=5.8.45.8.35.8.25.8.15.8.0'
- usethreads=defineuse5005threads=undefuseithreads=defineusemultiplicity=define
从结果中不难看出,在当前的Perl环境中提供了对ithreadsPerl线程模型的支持。
在Perl程序中,我们也可以通过使用Config模块来动态获取Perl线程模型的相关信息,例如
清单2.Perl程序中动态获取当前Perl线程模型
- #!/usr/bin/perl
- #
- useConfig;
- if($Config{useithreads}){
- printf("Helloithreads\n")
- }
- elsif($Config{use5005threads}){
- printf("Hello5005threads\n");
- }
- else{
- printf("Cannotsupportthreadinyourperlenvironment\n");
- exit(1);
- }
值得一提的是,对于5005threads和ithreadsPerl线程模型,Perl同时只能支持其中的一种。你不可能在某一个Perl环境中同时使用这两种Perl线程模型。本文后面讨论的所有内容都是基于ithreadsPerl线程模型的。
【编辑推荐】