在线程之间设计具有多线程和数据共享的perl脚本

时间:2010-08-11 11:34:51

标签: multithreading perl

我正在编写一个perl脚本来运行某种管道。我首先阅读一个带有一堆参数的JSON文件。然后我做了一些工作 - 主要是构建一些稍后需要的数据结构,并调用生成一些我保留引用的输出文件的外部程序。

我通常会为每个步骤使用子程序。每个这样的子程序通常会将一些数据写入一个没有其他子程序写入的唯一位置(即散列中的特定键),并读取其他子程序可能生成的数据。

如果顺序完成这些步骤可能需要几分钟,但是大多数步骤可以与我知道如何处理的一些简单的依赖逻辑(使用线程和队列)并行运行。所以我想知道如何实现它以允许在线程之间共享数据。你会建议框架是什么?也许使用一个对象(我只有一个实例)并将所有共享数据保存在$self中?也许 一个简单的脚本(没有对象)与一些“全局”共享变量? ......

我显然更喜欢简单明了的解决方案。

2 个答案:

答案 0 :(得分:3)

阅读threads::shared。默认情况下,您可能知道,perl变量不是共享的。但是你将shared属性放在它们上面,它们就是。

my %repository: shared;

然后,如果您想同步对它们的访问,最简单的方法是

{   lock( %repository );
    $repository{JSON_dump} = $json_dump;
}
# %respository will be unlocked at the end of scope.

但是你可以使用Thread::Queue,它应该是无muss的,并且也可以这样做:

$repo_queue->enqueue( JSON_dump => $json_dump );

然后您的消费者线程可以:

my ( $key, $value ) = $repo_queue->dequeue( 2 );
$repository{ $key } = $value;

答案 1 :(得分:1)

你当然可以在Perl中做到这一点,我建议你看看perldoc threadsperldoc threads::shared,因为这些手册页最能描述在Perl中使用线程时遇到的方法和陷阱。

我建议您使用的是Gearman等队列管理系统,它具有各种接口,包括Perl模块。这允许您根据需要创建任意数量的“工作者”(子实际执行工作)并创建一个简单的“客户端”,它将安排相应的任务然后整理结果,而不需要使用特定的hashref键完成任务或类似事情。

这种方法也可以更好地扩展,如果你选择的话,你可以在不同的机器上拥有客户和工人(甚至是经理)。

其他队列系统,例如TheSchwartz,将不会被指示,因为它们缺少Gearman提供的反馈/结果。对于所有效果,使用Gearman这种方式就像你描述的线程系统一样,没有任何基于线程的系统可能最终遭受的麻烦和麻烦:必须使用信号量锁定变量,连接线程。