【发布时间】:2015-07-08 16:53:56
【问题描述】:
我有一个类似于下面的代码。我有一个主脚本正在调用另一个名为 initial.pm 的模块。 initial.pm 打开与 AMQP 服务器(在我的情况下为 RabbitMQ)的连接,并使用 Net::AMQP::RabbitMQ 库建立连接。一切正常,除了当我尝试加入我的线程时,我得到 segmentation fault。
我认为 Net::AMQP::RabbitMQ 不是线程安全的。但这仅由主线程使用。如果您只是复制并粘贴下面的代码,我很确定您可以重现该错误。
我该如何解决?
main.pl
#!/usr/bin/perl
use Cwd qw/realpath/;
use File::Basename qw/dirname/;
use lib 'lib';
use threads;
use threads::shared;
use initial;
my @threads = ();
my $run :shared = 1;
my $init = load initial($name);
$SIG{'TERM'} = sub {
$run = 0;
};
threads->create(\&proc1);
threads->create(\&proc2);
while($run){
sleep(1);
print "I am main thread\n";
}
$_->join() for threads->list();
sub proc1 {
while($run){
sleep(1);
print "I am child thread 1 \n"
}
}
sub proc2 {
while($run){
sleep(1);
print "I am child thread 2 \n";
}
}
lib/initial.pm
package initial;
use Net::AMQP::RabbitMQ;
use Cwd qw/realpath/;
use File::Basename qw/dirname/;
my $mq;
my $stop = 0;
sub load {
my $class = shift;
my $self = {};
connectq();
bless $self,$class;
return $self;
}
sub connectq {
$mq = Net::AMQP::RabbitMQ->new();
my ($host,$port,$user,$pass) = ('localhost','5672','guest','guest');
$mq->connect($host, {
user => $user,
password => $pass,
port => $port,
timeout => 10,
});
$mq->channel_open(1);
$mq->consume(1, 'logger');
}
1;
【问题讨论】:
-
Perl 线程很重。每个线程都有自己的
$init变量副本,并且initial类的线程安全性将是相关的。在创建两个线程之后,您是否有更好的运气来分配$init分配? -
为什么将
join移回信号处理程序。这没有任何意义。 -
显而易见的猜测是 Net::AMQP::RabbitMQ 不是线程安全的
-
我更新了代码,请立即查看。有同样的问题。是 Net::AMQP::RabbitMQ 不是线程安全的。有什么解决办法吗?
-
@mob 如果我在创建线程后调用初始类,我看不到错误。但这只是更大代码的一部分,并且在创建线程后每次调用类都不是我的解决方案。有没有办法告诉 perl 不要复制我的 $init 变量?
标签: multithreading perl