【问题标题】:Perl - multithreading / fork / synchronize problem:Perl - 多线程/fork/同步问题:
【发布时间】:2021-08-19 09:23:40
【问题描述】:

我正在尝试作为以下代码的示例:

    my $milon;
    my $pid = fork();
    die if not defined $pid;    
    if (not $pid) 
    {
        $milon->{$pid} = $pid;
        exit;
    }
    
    $milon->{3} = 4;        
    my $finished = wait();  
    print( "debug10: TEST = ", Dumper($milon));

输出:

debug10: TEST = $VAR1 = {
          '3' => 4
        };

如何让字典同时保留3 => 4$pid => $pid? 不一定要分叉,可以是多线程或非阻塞 IO,根据您的想法哪个更好。

这当然是一个例子,我只是想从这个例子中总结出我的真实代码。

【问题讨论】:

标签: multithreading perl


【解决方案1】:

您需要一些在线程/进程之间共享的内存。最简单的可能是使用基于解释器的threadsthreads::shared。例如:

use threads;
use threads::shared;

my %milon :shared;

for (1 .. 2) {
    threads->create(sub {
        my $tid = threads->tid();
        $milon{$tid} = $tid;
    });
}

$milon{3} = 4;

$_->join for threads->list; # Wait for all threads to be done

print Dumper \%milon;

这个输出:

$VAR1 = {
          '1' => 1,
          '2' => 2,
          '3' => 4
        };

【讨论】:

  • 嗨,你的例子有效,但我想问一个指针的情况......谢谢意味着我不想将 milon 声明为 %milon,而是声明为带有 milon 的 $milon -> {value} 等。我用调整做了你的确切代码,但我得到:Perl exited with active threads: 0 running and unjoined 2 finished and unjoined 0 running and detached
  • @urie 您需要手动share 要共享的每个散列或数组。如果您希望 $milon 成为哈希引用,那么您可以使用 share(my $milon = {}) 例如。
  • @urie shared_clone 用于复杂的数据结构。查看示例here
  • @urie 另请注意,线程和它们之间的数据共享具有微妙之处。我建议您仔细研究文档,并在此处查找和查看好的示例。
  • @Dada 任何想法如果字典的值到达其他变量,我该如何使用此代码?有没有办法做到这一点而不必将所有内容都更改为共享?
【解决方案2】:

以下示例代码演示了使用 fork() 在并行执行中计算数组 @numbers(共 100 个)中的数字的平方

分配给$SIG{CHLD} 信号的REAPER 函数会清理已完成的子进程,以避免僵尸进程在进程表中徘徊。

调查fork() 方法是否适合您的问题/任务。

use strict;
use warnings;

use POSIX qw(strftime :sys_wait_h);
use Time::HiRes qw(usleep);

my $limit   = 10;
my $threads = $limit;
my @numbers = map { int(rand(100)) } 1..100;

sub REAPER {
    local $!;

    while( (my $pid = waitpid(-1, WNOHANG) ) > 0 && WIFEXITED($?) ) {
        $threads++;
    }

    $SIG{CHLD} = \&REAPER;
}

$SIG{CHLD} = \&REAPER;

for ( @numbers ) {
    while( $threads == 0 or $threads > $limit ) { usleep(1) }

    my $pid = fork();

    die $! unless defined $pid;

    if( $pid ) {
        # parent
        $threads--;
    } else {
        # child
        my $n = compute_square($_);
        printf "Process %6d: %3d => %d\n", $$, $_, $n;
        exit 0;
    }
}

sub compute_square {
    my $num = shift;

    return $num*$num;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多