我在Windows平臺上遇到以下非常簡單和小型的Perl腳本問題。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] Got string: '30'. [Thread_1] Got string: '29'. [Thread_2] Got string: '28'. [Thread_1] Got string: '27'. [Thread_2] Got string: '26'. [Thread_1] Got string: '25'. [Thread_1] Got string: '23'. [Thread_2] Got string: '24'. [Thread_2] Got string: '20'. [Thread_2] Got string: '19'. [Thread_1] Got string: '22'. [Thread_4] Got string: '18'. [Thread_5] Got string: '15'. [Thread_2] Got string: '17'. [Thread_2] Got string: '12'. [Thread_3] Got string: '21'. [Thread_4] Got string: '14'. [Thread_4] Got string: '7'. [Thread_1] Got string: '16'. [Thread_6] Got string: '11'. [Thread_2] Got string: '10'. [Thread_2] Got string: '2'. [Thread_3] Got string: '8'. [Thread_5] Got string: '13'. [Thread_8] Got string: '6'. [Thread_4] Got string: '5'. [Thread_1] Got string: '4'. [Thread_6] Got string: '3'. [Thread_7] Got string: '9'. [Thread_2] Got string: '1'. $
然而,在Windows(Perl的v5.10.1)我得到一個爛攤子:
C:\>perl Z:\tmp\thr2.pl [Thread_1] Got string: '30'. [Thread_2] Got string: '29'. [Thread_2] Got string: '21'. [Thread_6] Got string: '26'. [Thread_5] Got string: '25'. [Thread_5] Got string: '17'. [Thread_8] Got string: '23'. [Thread_1] Got string: '22'. [Thread_1] Got string: '14'. [Thread_2] Got string: '20'. [Thread_6] Got string: '18'. [Thread_7] Got string: '24'. [Thread_7] Got string: '9'. [Thread_8] Got string: '15'. [Thread_3] Got string: '28'. [Thread_3] Got string: '6'. [Thread_4] Got string: '12'. [Thread_2] Got string: '[Thread_4] Got string: '27'. 19'. [Thread_6] Got string: '10'. [Thread_5] Got string: '16'. [Thread_7] Got string: '8'. [Thread_8] Got string: '7'. [Thread_1] Got string: '13'. [Thread_3] Got string: '5'. [Thread_4] Got string: '4'. [Thread_2] Got string: '11'. [Thread_6] Got string: '[Thread_2] Got string: '3'. [Thread_5] Got string: '2'. 1'. C:\>
當我通過反引號從線程函數運行一個命令(無所謂命令)來收集它的輸出時,問題就會發生。
我對Perl中的線程和Windows上的Perl的使用經驗非常有限。 我總是儘量避免在Perl中使用線程,但是這次我必須使用它們。
我無法在perldoc和Google中找到答案。 有人能解釋我的腳本有什麼問題嗎?
在此先感謝!
一個解決辦法,我發現是改變「打印」到「打印STDERR」,然後運行該腳本「的perl Z:\ tmp目錄\ thr2.pl 2>&1」 – 2011-04-29 12:01:39
不過,我不知道爲什麼這個修復問題。我知道STDERR是無緩衝的,但我嘗試了使用autoflush的STDOUT,但它不起作用。 – 2011-04-29 12:09:23