代码之家  ›  专栏  ›  技术社区  ›  Robert S. Barnes Antoni

如何在Perl中存储调用之间的每个线程状态?

  •  2
  • Robert S. Barnes Antoni  · 技术社区  · 15 年前

    现在根据我在Perl下的理解,除非显式共享,否则所有数据都是私有的。

    #!/usr/bin/perl -w
    
    use strict;
    use threads;
    
    { # closure to create local static variable
        my $per_thread_state = 0;
    
        sub foo {
            my $inc = shift;
            $per_thread_state += $inc;
    
            return $per_thread_state;
        }
    }
    
    my $inc = 0;
    
    threads->create(
        sub { 
            my $inc = shift;
            my $i = $inc; 
            while (--$i) { 
                threads->yield(); 
                print threads->tid().":".foo($inc)."\n";
            }
        }, $inc
    ) while (++$inc < $ARGV[0]);
    
    $_->join() foreach threads->list();
    

    当我运行它时,它看起来像我期望的那样工作,但我只是想确定一下,因为我找不到任何明确讨论这样做的文档。

    有人能给我指一些看起来很正式的东西吗?

    另一件看起来很奇怪的事情是,线程似乎总是按照创建顺序运行,并且由于某种原因不会交错。例如,如果我运行:

    ./tsd.pl 100
    

    一切打印得井井有条。如果有必要的话,我会使用Ubuntu 9.04。

    2 回复  |  直到 15 年前
        1
  •  2
  •   Zaid    15 年前

    如果您运行的是Perl5.9.4+,那么这似乎是使用 state 关键词。如果 状态 已启用,只有您的 foo() 子例程将能够修改 $per_thread_state .

    以下是方法:

    use feature 'state';
    
    sub foo {
        state $per_thread_state;
        my $inc = shift;
        $per_thread_state += $inc;
        return $per_thread_state;
    }
    

    记住启用 状态 perlsub ):

    从Perl5.9.4开始,您可以用state关键字代替my来声明变量。但是,要想实现这一点,您必须事先启用该特性,或者使用特性pragma,或者在一行程序中使用-E。

    perlsub还有一个关于 Persistent Private Variable with Closures

        2
  •  1
  •   Eric Strom    15 年前

    将Perl的线程视为处理IPC和分叉进程的更方便的方法通常会有所帮助。每次呼叫 threads->create(...) 克隆当前解释器以及解释器中的所有内容,因此每个线程都将获得各自独立的解释器副本 foo() $per_thread_state

    线程按创建顺序运行主要是由于Perl和操作系统中的实现细节(主要是因为它们各自的执行时间低于操作系统的最短执行时间片)。要交错线程,可以使用 sleep 而不是屈服(或者让线程做一些实际的工作)。