2012-01-25 24 views
3

別の投稿に明示的な例がある場合は、お知らせください。スレッドからのインターリーブ印刷に問題があります。すべてのスレッドで共有変数を使用してスレッドを制御しようとしています。以下の擬似コードは私のコードを強調し、問題を与えてくれます。スレッドを印刷待ちにするためにすべてを試しました。現在、わずかな出力回線しか破棄されていません。Perlスレッドが正しく印刷されない

#!/usr/bin/perl                                 
use threads; 
use threads::shared; 

my $PRINTFLAG :shared = 1; 

Run_Threads(); 

sub Do_stuff{ 

    lock($PRINTFLAG); 
    cond_wait($PRINTFLAG) until $PRINTFLAG == 1; 
    $PRINTFLAG = 0; 
    print "$working\n"; 
    $PRINTFLAG =1; 
} 

スレッドを生成するためのサブスレッド。

sub Run_Threads{ 

    my @threads; 

    for (my $i = 1; $i <= 5; $i++){ 
     push @threads, threads->create(\&Do_stuff); 
    } 

    foreach (@threads){ 
     $_->join; 
    } 
} 
+0

私はいつも「スレッド」と「正しく印刷されません」と同じ文章で私は恐怖感を感じ始めます。これは一般的に適切に行うのは難しいことです。 –

答えて

5

各スレッドは独自のハンドルを持っているため、独自の出力バッファいることと思われます。 threads::sharedのメカニズムを使ってPerlファイルハンドルを共有できないことを考えると、それほど驚くことではありません。

つまり、ロックを解除する前にハンドルのバッファをフラッシュする必要があります。前->flush->autoflushメソッドを使用する(ただし$|=1;用):

select->flush();  # Flush handle currently default for print. 

それとも、そのハンドルへのすべての印刷後に自動的にフラッシュのperlを持つことができます:あなたは、明示的にそれを行うことができます

select->autoflush(1); # Autoflush handle currently default for print. 
$| = 1;    # Autoflush handle currently default for print. 

注意Perl 5.14の場合は、IO::Handleもロードする必要があります。ところで


my $PRINTFLAG :shared = 1; 
lock($PRINTFLAG); 
cond_wait($PRINTFLAG) until $PRINTFLAG == 1; 
$PRINTFLAG = 0; 
print "$d\n"; 
$PRINTFLAG =1; 

は、それがThreads::Queueを使用するために、単純な/より良いのスレッドで私の経験から

my $PRINTMUTEX :shared; 
lock($PRINTMUTEX); 
print "$d\n"; 
+0

$ PRINTFLAGはファイルハンドルではありません。私は標準的な方法で印刷を終えている間にスレッドを停止させるためにそれを使用しようとしています。ファイルハンドルに印刷する必要がありますか?内部のバッファリングが私を悩ませていますか?私はバッファをゼロに設定すべきですか? –

+0

@ zev.kronenberg、Re: "$ PRINTFLAGはファイルハンドルではありません"、私は知っています。 – ikegami

+0

@ zev.kronenberg、Re "ファイルハンドルに印刷する必要がありますか?"あなたが私たちの助けを求めているので、私はそう想像しています。 ?!?! – ikegami

3

に単純化することができます。

私は2つのキューを持っています.1つはスレッドを実行するタスク用で、もう1つはスレッドからの結果用です。

私のマスタースレッドでは、結果のキューを確認してから印刷します。したがって、結果ファイルなどにアクセスする競合はありません。

+0

今後これを試してみる必要があります! –

関連する問題