Windows プラットフォームで、次の非常に単純で小さな Perl スクリプトに問題があります。
use strict;
use warnings;
use threads;
use threads::shared;
my $print_mut : shared;
my $run_mut : shared;
my $counter : shared;
$counter = 30;
###############################################################
sub _print($)
{
lock($print_mut);
my $str = shift;
my $id = threads->tid();
print "[Thread_$id] $str";
return;
}
###############################################################
sub _get_number()
{
lock($counter);
return $counter--;
}
###############################################################
sub _get_cmd($)
{
my $i = shift;
if ($^O eq 'MSWin32')
{
return qq{cmd /c "echo $i"};
}
return "echo $i";
}
###############################################################
sub thread_func()
{
while ((my $i = _get_number()) > 0)
{
my $str = 'NONE';
{
lock($run_mut);
my $cmd = _get_cmd($i);
$str = `$cmd`;
}
chomp $str;
_print "Got string: '$str'.\n";
}
return;
}
###############################################################
# Start all threads
my @threads;
for (1 .. 8)
{
my $thr = threads->create('thread_func');
push @threads, $thr;
}
# Wait for completion of the threads
foreach (@threads)
{
$_->join;
}
###############################################################
私の Linux ボックス (Perl v5.10.0) では、正しい (期待される) 結果が得られます。
$ perl ~/tmp/thr2.pl [Thread_1] 文字列を取得しました: '30'。 [Thread_1] 文字列 '29' を取得しました。 [Thread_2] 文字列を取得しました: '28'。 [Thread_1] 文字列を取得しました: '27'。 [Thread_2] 文字列を取得しました: '26'。 [Thread_1] 文字列を取得しました: '25'。 [Thread_1] 文字列を取得しました: '23'。 [Thread_2] 文字列を取得しました: '24'。 [Thread_2] 文字列を取得しました: '20'。 [Thread_2] 文字列を取得しました: '19'。 [Thread_1] 文字列 '22' を取得しました。 [Thread_4] 文字列「18」を取得しました。 [Thread_5] 文字列「15」を取得しました。 [Thread_2] 文字列を取得しました: '17'。 [Thread_2] 文字列 '12' を取得しました。 [Thread_3] 文字列を取得しました: '21'。 [Thread_4] 文字列 '14' を取得しました。 [Thread_4] 文字列 '7' を取得しました。 [Thread_1] 文字列 '16' を取得しました。 [Thread_6] 文字列 '11' を取得しました。 [Thread_2] 文字列 '10' を取得しました。 [Thread_2] 文字列 '2' を取得しました。 [Thread_3] 文字列 '8' を取得しました。 [Thread_5] 文字列 '13' を取得しました。 [Thread_8] 文字列 '6' を取得しました。 [Thread_4] 文字列 '5' を取得しました。 [Thread_1] 文字列 '4' を取得しました。 [Thread_6] 文字列 '3' を取得しました。 [Thread_7] 文字列 '9' を取得しました。 [Thread_2] 文字列 '1' を取得しました。 $
ただし、Windows (Perl v5.10.1) では混乱します。
C:\>perl Z:\tmp\thr2.pl [Thread_1] 文字列を取得しました: '30'。 [Thread_2] 文字列を取得しました: '29'。 [Thread_2] 文字列を取得しました: '21'。 [Thread_6] 文字列 '26' を取得しました。 [Thread_5] 文字列 '25' を取得しました。 [Thread_5] 文字列「17」を取得しました。 [Thread_8] 文字列 '23' を取得しました。 [Thread_1] 文字列 '22' を取得しました。 [Thread_1] 文字列を取得しました: '14'。 [Thread_2] 文字列を取得しました: '20'。 [Thread_6] 文字列「18」を取得しました。 [Thread_7] 文字列 '24' を取得しました。 [Thread_7] 文字列 '9' を取得しました。 [Thread_8] 文字列 '15' を取得しました。 [Thread_3] 文字列 '28' を取得しました。 [Thread_3] 文字列 '6' を取得しました。 [Thread_4] 文字列 '12' を取得しました。 [Thread_2] 取得した文字列: '[Thread_4] 取得した文字列: '27'。 19'. [Thread_6] 文字列 '10' を取得しました。 [Thread_5] 文字列「16」を取得しました。 [Thread_7] 文字列 '8' を取得しました。 [Thread_8] 文字列 '7' を取得しました。 [Thread_1] 文字列を取得しました: '13'。 [Thread_3] 文字列 '5' を取得しました。 [Thread_4] 文字列 '4' を取得しました。 [Thread_2] 文字列 '11' を取得しました。 [Thread_6] 取得した文字列: '[Thread_2] 取得した文字列: '3'。 [Thread_5] 文字列 '2' を取得しました。 1'. C:\>
この問題は、スレッド関数からバックティックを介してコマンド (コマンドは関係ありません) を実行して出力を収集すると発生します。
Perl のスレッドと Windows 上の Perl の経験は非常に限られています。私はいつも Perl でスレッドをまったく使用しないように努めてきましたが、今回はそれらを使用する必要があります。
perldoc と Google で答えを見つけることができませんでした。誰かが私のスクリプトの何が問題なのか説明してもらえますか?
前もって感謝します!