我在 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 中找到答案。有人可以解释我的脚本有什么问题吗?
提前致谢!