2010-07-20 69 views
9

我正在尝试编写一个Perl程序并将其写入线程。问题是我读过一些模块不是“线程安全”的。我怎么知道一个模块是否线程安全?我查了一下列表,找不到一个。Perl线程安全模块

为了测试一个模块,我经常使用(文字:: CSV_XS)我尝试下面的代码了:

use strict; 
use warnings; 
use threads; 
use threads::shared; 
require Text::CSV_XS; 

my $CSV = Text::CSV_XS->new ({ binary => 1, eol => "\n" }) or die("Cannot use CSV: ".Text::CSV->error_diag()); 
open my $OUTPUT , ">:encoding(utf8)", "test.csv" or die("test.csv: $!"); 

share($CSV); 

my $thr1 = threads->create(\&sayHello('1')); 
my $thr2 = threads->create(\&sayHello('2')); 
my $thr3 = threads->create(\&sayHello('3')); 


sub sayHello 
{ 
my($num) = @_; 

print("Hello thread number: $num\n"); 

my @row = ($num); 
    lock($CSV);{ 
    $CSV->print($OUTPUT, \@row); 
    $OUTPUT->autoflush(1); 
    }#lock 
}#sayHello 

我收到的输出如下:

 
Hello thread number: 1 
Segmentation fault 

这是否意味着该模块不是线程安全的,还是另一个问题?

感谢

+1

尝试拿出可以引起分段错误最小的方案。 – mob 2010-07-20 04:47:21

回答

32

一般来说,核心和高能见度的模块线程安全的,除非他们的文档,否则说。

这就是说,有在您的文章的几个失误:

  1. share($CSV)
    这将清除$CSV(有福hashref),just as documented in threads。通常,要共享()复制对象之前的以进行初始化,或者在这种情况下可能会在线程之间共享()一些哑变量$lock变量。
    由于$CSV为底层XS保存状态,因此可能会导致未定义的行为。

    但这不是你的段错误。

  2. threads->create(\&sayHello('1'));
    您错误地在主线程中调用sayHello(1)并通过参考,它的返回值threads->create()的(假的)启动程序。 你的意思是说:

    threads->create(\&sayHello, '1'); 
    

    但是,这是不是你的段错误。

    编辑只是为了澄清 - 在这里一个糟糕的开局例程不无论如何风险SEGV threads::create如果无法识别的子程序名称或不CODE裁判在传递正确抱怨你的情况,。但是,您很快就会发生错误,无法达到此错误处理。)

  3. 编码不是线程安全的。
    再次as documented in encodingsencoding模块不是线程安全的。 这里是最小的代码,我能得到重现你的症状:

    use threads; 
    open my $OUTPUT , ">:encoding(utf8)", "/dev/null" or die $!; 
    threads->create(sub {})->join; 
    

    这就是Perl的5.12.1与线程-1.77在i686-linux的线程多,如果你有兴趣。放下“utf8”的魔法,它工作得很好。

    这是你的内存设计缺陷

+0

很好的答案... – masonk 2010-07-20 13:37:35

+0

这节省了我几个小时的搜索我的段错误的原因。谢谢! – 2011-04-18 19:26:54