微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Windows中的multithreadingPerl脚本中的反引号问题

我在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]得到了string:'30'。

[Thread_1]得到了string:'29'。

[Thread_2]得到string:'28'。

[Thread_1]得到string:'27'。

[Thread_2]得到string:'26'。

[Thread_1]得到string:'25'。

[Thread_1]得到string:'23'。

[Thread_2]得到string:'24'。

[Thread_2]得到string:'20'。

[Thread_2]得到string:'19'。

[Thread_1]得到string:'22'。

[Thread_4]得到string:'18'。

[Thread_5]得到string:'15'。

[Thread_2]得到string:'17'。

[Thread_2]得到string:'12'。

[Thread_3]得到string:'21'。

[Thread_4]得到string:'14'。

[Thread_4]得到string:'7'。

[Thread_1]得到的string:'16'。

[Thread_6]得到了string:'11'。

[Thread_2]得到string:'10'。

[Thread_2]得到string:'2'。

[Thread_3]得到string:'8'。

[Thread_5]得到string:'13'。

[Thread_8]得到的string:'6'。

[Thread_4]得到的string:'5'。

[Thread_1]得到了string:'4'。

[Thread_6]得到的string:'3'。

[Thread_7]得到string:'9'。

[Thread_2]得到string:'1'。

$

但是,在Windows(Perl v5.10.1)中,我弄得一团糟:

C:> perl Z: tmp thr2.pl

[Thread_1]得到了string:'30'。

[Thread_2]得到string:'29'。

[Thread_2]得到string:'21'。

[Thread_6]得到string:'26'。

[Thread_5]得到string:'25'。

[Thread_5]得到了string:'17'。

[Thread_8]得到string:'23'。

[Thread_1]得到string:'22'。

[Thread_1]得到的string:'14'。

[Thread_2]得到string:'20'。

[Thread_6]得到了string:'18'。

[Thread_7]得到string:'24'。

[Thread_7]得到string:'9'。

[Thread_8]得到string:'15'。

[Thread_3]得到string:'28'。

[Thread_3]得到的string:'6'。

[Thread_4]得到了string:'12'。

[Thread_2]得到的string:'[Thread_4]得到的string:'27'。

19' 。

[Thread_6]得到string:'10'。

[Thread_5]得到的string:'16'。

[Thread_7]得到string:'8'。

[Thread_8]得到了string:'7'。

[Thread_1]得到了string:'13'。

[Thread_3]得到了string:'5'。

[Thread_4]得到的string:'4'。

[Thread_2]得到string:'11'。

[Thread_6]得到的string:'[Thread_2]得到的string:'3'。

[Thread_5]得到了string:'2'。

1。

C:>

当我通过反引号从线程函数运行一个命令(无关紧要的命令)来收集它的输出时,问题就发生了。

为什么在反引号中出现语法错误,尽pipe它在terminal工作?

如何在perl中加载STDIN以反引号(无需写入临时文件

我在Perl中的线程和在Windows上的Perl方面的经验非常有限。 我总是尽量避免在Perl中使用线程,但是这次我必须使用它们。

我没有设法在perldoc和Google中find答案。 有人能解释我的脚本有什么问题吗?

提前致谢!

我可以在我的WinXP上重新创建这个问题,结果相同。 但是,这似乎只影响STDOUT。

如果我打印到一个文件,问题不会出现,也不会出现在我使用STDERR的时候,就像德米特里所建议的那样。 但是,如果我写入STDOUT和一个文件,它会出现。 这是一个线索。

在打印中添加一个反引号变量会导致问题出现在两个地方,每个连接之前。

在测试时,我决定chomp()是不够的,所以我补充说

$str =~ s/[^w]+//g;

有了这个有趣的结果:

[Thread_6] Got string: 'Thread_4Gotstring1925'.

这似乎意味着$str实际上保存了另一个线程的整个打印缓冲区。 至少可以说,这很奇怪。

除非这个…

两个线程在同一时间运行:

print "[Thread_4] Got string: '19'.n" $str = `echo 25`

打印和回应可能共享相同的STDOUT缓冲区,所以它们都进入$str ,结果打印:

chomp "[Thread_4] Got string: '19'.n25n" print "[Thread_6] Got string: [Thread_4] Got string: ''19'n25'.n"

总之,一个Windows的问题。 如果您想“解决”问题,请确保回显和打印都被锁定的值覆盖。 将thread_func移动到thread_func下面的_print应该提供一个干净的打印。 即:

{ lock($run_mut); my $cmd = _get_cmd($i); $str = `$cmd`; chomp $str; _print "Got string: '$str'.n"; }

一个有趣的方法来验证这将是用一些写入STDERR的Windows命令替换回声,并看看是否与perl中打印到STDERR的打印冲突。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐