Perl线程安全模块

时间:2010-07-20 02:14:27

标签: multithreading perl module

我正在尝试使用我编写的Perl程序并对其进行处理。问题是我读到一些模块不是“线程安全的”。我如何知道模块是否是线程安全的?我环顾四周找不到一个清单。

要测试我经常使用的一个模块(Text :: 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 个答案:

答案 0 :(得分: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;
    

    如果您感兴趣的话,那就是i686-linux-thread-multi上的线程为1.77的perl 5.12.1。放弃“utf8”魔法,它的效果很好。

    这是你的段错误