はちゅにっき

こっちのブログはまったり更新

Perl でプロセスの待ち合わせをする

たとえば以下のようなプログラムを Perl で書いて

#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/ say /;
use Parallel::ForkManager;
use Time::HiRes ( );
 
my $process = 10;
my $pm = Parallel::ForkManager->new($process);
 
for (1..$process) {
    if ($pm->start) {
        Time::HiRes::sleep(0.2);  # fork に時間がかかることを想定
        next;
    }

    # 子プロセスの処理開始時刻を表示
    say "[$$] ", Time::HiRes::time( );
 
    $pm->finish;
}
 
$pm->wait_all_children;

これを実行してみると

[3107] 1381815422.89502
[3108] 1381815423.09763
[3109] 1381815423.30142
[3110] 1381815423.50445
[3111] 1381815423.70717
[3112] 1381815423.91102
[3113] 1381815424.1142
[3114] 1381815424.31746
[3115] 1381815424.52011
[3116] 1381815424.72334

当然、親プロセスが 0.2 秒休んでいるため、子プロセスの処理開始時刻は約0.2秒間隔のバラバラに。
今回は sleep しているので当然ですが、fork って結構時間がかかる処理なので特別 sleep を入れなくても、子プロセスの処理開始時刻はバラバラになりがち。
普通はこれでも全然かまわないんですが、fork が完了するのを待って子プロセスを一斉に開始させたい!とか、fork 完了後に親プロセスが何らかの処理を行ない、その後一斉に子プロセスを開始させたい!とか、特定の条件が揃うまで子プロセスの実行を停止させておきたい!なんてときには、プロセスの "待ち合わせ" が必要になります。
滅多にそんなことは発生しないんだろうけれど、なんか今回はそういう要件があってだな。。。
というわけで、今回は手っ取り早くセマフォを使ってプロセスの待ち合わせをしてみることに。

続きを読む