如何在perl中使用信号量

时间:2014-08-21 06:55:20

标签: perl

帮助我在打印到输出文件" temp.out"。

时,如何以及在哪里使用信号量来控制?

open(OUT,">temp.out");

open(IN,"temp.txt");

while(<IN>)
{
    $line = $_;

- &GT;对于每一行,我想使用thread_main做一些工作。

&#34; thread_main - &gt;分支到thread1,thread2,thread3;&#34;     thread1对file1.txt执行IO(读取)操作 - 应与sem1同步     线程2对file2.txt执行IO(读取)操作 - 应与sem2同步     thread3对file3.txt执行IO(读取)操作 - 应该使用sem3进行sysn

thread1 -> returns var1 
`var1 = thread1->join();` thread2 works on thread1 return data
thread2 -> returns var2
`var2 = thread1->join();` thread3 works on thread2 return data
thread3 -> returns var3
thread3->join();

这些线程最终会出现一些我要打印到文件中的变量。    printf(OUT "%s\t%s\t%s\t%s\n",$var1,$var2,$var3); - &gt;应该与sem_main同步 }

2 个答案:

答案 0 :(得分:1)

你说你想要使用信号量,但我不认为你真的这样做 - 信号量作为并发编程中的一个特定含义,它基本上是一个全球性的旗帜&#39;处理资源和所有权的某种方式和限制。

如果这是您所需要的,那么您可以使用lock实现基本版本,使用Thread::Semaphore实现更全功能的版本;

然而,在我看来,你不是,你只是试图整理线程中的数据。

对于单个值 - 只需从标量上下文开始,然后使用return / join

E.g:

 sub worker_thread {
      #do stuff;
       return $value; 
 }


 my $thr = threads -> create ( \&worker_thread ); 

 #will block until 'thr' finishes. 
 my $result_from_thread = $thr -> join(); 

但是,我一般主张使用Thread::Queue使用enqueuedequeue(以及end)在线程周围传递值。

my $result_q = Thread::Queue -> new();

sub worker_thread {
    my ( $filename ) = @_; 
    #run loop
        #do stuff
        $result_q -> enqueue ( $result );
    #exit loop
 }

 #create threads - use a loop if you need several, passing parameters is good too. 
foreach my $filename ( @file_list ) {
    my $thr = threads -> create ( \&worker_thread, $filename ); 
}

foreach my $thread ( threads -> list() ) {
   $thread -> join();
}

$result_q -> end();

while ( my $result = $result_q -> dequeue ) {
   #do something with $result;
}

如果您也拥有大量文件,则可以使用此方法 - 产生大量线程会很快变得昂贵,但您可以创建一个“工作人员”池。线程,并为它们提供队列中的文件名列表。

我建议你考虑为什么你在这里进行线程化。通常进行线程处理是为了避免阻塞调用并获得更多的CPU时间。读取文件是阻止IO的一种形式,但如果它们来自同一存储子系统,那么并行执行3并不一定能让您获得更好的性能。您的限制因素不会是您的CPU /内存,而是您的磁盘旋转速度 - 您无法改进的东西,并且可能会因尝试线程而变得更糟。

答案 1 :(得分:0)

有趣的是我有1个多线程perl,它基于这个逻辑工作。在我所有的线程之后,我执行了2个方法:

sub is_running(){
    my $threads_num=0;
    foreach (@threads){
        if ($_-is_joinable()){
            $threads_num++;
        }
    }
    if ( $threads_num == @machines ) {
        return 0; # All threads are completed
    }
    return 1; # Not all threads are completed
}

这个是检查所有线程是否已完成,因为根据您的实现,主线程可以退出而无需等待已经启动的子线程。

my $count=30;
while ((is_running)&&($count  0)){
    $count--;
    sleep(1);
}

由于我正在使用线程执行ssh命令,如果其中一些线程卡在某处,则会超时。

超时后我称之为这个方法:

sub return_result(){
    my $machine_num=0;
    foreach (@threads){
        if ($_-is_joinable()){
            push(@results,$machines[$machine_num].$_-join());
            if ( $results[$machine_num] !~ OK){
                $rc=1;
            }
        }else{
            my $id=$_-tid();
            push(@results,$machines[$machine_num] TIMEOUT);
            $_-detach();
            $rc=1;
        }
        $machine_num++;
    }
    if ( $rc == 0 ) {
        $result=The execution of '$com' has returned '$res' on all hosts OK ;
    }else{
    $result=The execution of '$com' has NOT returned '$res' on some hosts ERROR ;
    }
    foreach(@results){
        $result.=$_;
    }
    return $result br;
}

基本上它检查一个线程是否可以连接(已完成它的工作)将其结果推送到一个数组。