Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 在Perl中跨线程共享文件数据的聪明方法_Multithreading_Perl - Fatal编程技术网

Multithreading 在Perl中跨线程共享文件数据的聪明方法

Multithreading 在Perl中跨线程共享文件数据的聪明方法,multithreading,perl,Multithreading,Perl,我正在寻找一种可靠的(可能是聪明的)方法,在Perl中通过可变数量的线程共享文件数据。我希望有一个设置,其中主线程读取文件中的行,而其他工作线程处理单个条目 到目前为止,我已经尝试过使用Thread::Queue,但没有太多的好运气。当我到达文件末尾时,大多数线程都处于阻塞状态,等待主线程完成读取后从中读取数据。因此,线程在某种程度上陷入了困境,join()无法将其卷回 当对队列使用非阻塞访问时,线程倾向于陷入“尝试获取数据,而不是未定义的数据,尝试获取数据…”的紧密循环中,这最终会导致CPU崩

我正在寻找一种可靠的(可能是聪明的)方法,在Perl中通过可变数量的线程共享文件数据。我希望有一个设置,其中主线程读取文件中的行,而其他工作线程处理单个条目

到目前为止,我已经尝试过使用Thread::Queue,但没有太多的好运气。当我到达文件末尾时,大多数线程都处于阻塞状态,等待主线程完成读取后从中读取数据。因此,线程在某种程度上陷入了困境,join()无法将其卷回

当对队列使用非阻塞访问时,线程倾向于陷入“尝试获取数据,而不是未定义的数据,尝试获取数据…”的紧密循环中,这最终会导致CPU崩溃而不工作。即使只有一个工作线程,每个线程通常也会得到至少几个紧循环的迭代。加入sleep()并没有太大帮助,因为它只接受整数值(sleep(0)是无用的,sleep(1)太慢)

最理想的情况是,我希望能够共享输入文件的流,并让每个线程锁定它,从中读取一行,然后解锁它,但禁止/不支持共享globs。我会先将整个文件加载到内存中,但考虑到它有4000万个条目(作为一个较低的估计),这并不太可行

这就是你们进来的地方。我需要一种简便的方法来实现主线程和工作线程之间的读卡器/处理器设置,这样就不会浪费过多的CPU等待数据,并且在读卡器到达文件末尾时,线程就处于join()可连接状态


非常感谢您的帮助或想法

使用主线程读取,然后用于处理行:

use strict;
use warnings;
use Coro;

my $sem = Coro::Semaphore->new(10); # maximum of ten semaphores
while my $line ( <$FILE> ) {
    $sem->down;
    async {
        dostuff($line);
        $sem->up;
    };
}
使用严格;
使用警告;
使用Coro;
我的$sem=Coro::信号量->新(10);#最多十个信号灯
而我的$line(){
$sem->下跌;
异步的{
多斯塔夫(行);
$sem->up;
};
}

这个小测试对我很有效。(我以前从未使用过螺纹,但在过去也使用过叉子和管道)。因此,基本上需要在请求线程加入之前告诉线程完成,为此,我在队列中添加了一个undef

#!/usr/bin/env perl

use strict;
use warnings;

use threads;
use Thread::Queue;

use constant MAX_THREADS => 5;

sub process_data
{
    my( $q ) = @_;
    while( defined( my $data = $q->dequeue() ) )
    {
        print "Thread[".threads->tid()."]: Processing data($data)\n";
    }

    print "Thread[".threads->tid()."]: Got end message\n";
} # END process_data

# Main program
{
    my @threads;
    my $q = Thread::Queue->new();
    foreach ( 1 .. MAX_THREAD )
    {
        push( @threads, async { process_data($q) } );
    }

    while( my $line = <STDIN> )
    {
        chop( $line );
        $q->enqueue( $line );
    }

    foreach my $thread ( @threads )
    {
        $q->enqueue( undef );
    }

    foreach my $thread ( @threads )
    {
        $thread->join();
    }
}
#/usr/bin/env perl
严格使用;
使用警告;
使用线程;
使用线程::队列;
使用常量MAX_线程=>5;
子进程数据
{
我的($q)=@;
while(已定义(my$data=$q->dequeue())
{
打印“线程[”.threads->tid().“]:处理数据($data)\n;
}
打印“线程[”.threads->tid().“]:获取结束消息\n”;
}#结束过程#U数据
#主程序
{
我的@threads;
my$q=线程::队列->新建();
foreach(1..MAX_螺纹)
{
push(@threads,async{process_data($q)});
}
while(我的$line=)
{
印章(行);
$q->排队($line);
}
foreach my$thread(@threads)
{
$q->排队(未定义);
}
foreach my$thread(@threads)
{
$thread->join();
}
}

使用
Time::HiRes::sleep
进行短时延迟,甚至(抖动)
选择undef、undef、undef、$short\u delay
。我唯一关心的是,在线处理比正常的行读取操作花费的时间更长。这意味着联合例程的启动速度将快于它们完成的速度。我相信会有一个平衡点,但我觉得这是一个机会。我可能太挑剔了。不错,我想我会试试看。我也在考虑类似的事情,但没有考虑使用
unde
作为结束标志。@ikegami编辑了我的答案。
async
块做什么?为什么它与以前的
threads->new(“process\u data”,$q)
有所不同/更好。不是抱怨,只是想学习,这是我第一次用perl玩线程。@Sodved,开始一个新线程。正如我在编辑消息中指定的,将参数传递给与未被引用堆栈相关的线程存在一些问题。我不记得确切的问题,但为了安全起见,我总是使用
async