2

假设我有一个线程:

sub     new {
        my      $class = shift;
        my      $self = ref $class || $class;

        bless { 'read_set'  => IO::Select->new,
                'write_set' => IO::Select->new,
                'error_set' => IO::Select->new }, $self;
}


sub     start {
        my      $self = shift;

        $self->{'thread'} = threads->create(\&worker_thr, $self);
        $self->{'thread'}->detach;
}

sub     worker_thr {
         my      $self = shift;

         while(1) {
                 my($read_active, $write_active, $error_active) = 
                    IO::Select->select(
                            $self->{'read_set'},
                            $self->{'write_set'},
                            $self->{'error_set'}, 
                            undef
                    );
         }

}       

由于我没有提供超时select()并且它无限期地阻塞,直到在一个描述符(好吧,“句柄”)集上检测到活动,如果另一个线程修改集的内容(例如添加一个新的套接字进行轮询)会发生什么?

相对于 Perl POSIX 线程实现,它是否以线程安全的方式实现?

如果没有,我想我可以将阻塞select()调用放在具有自己范围的块中并锁定集合,或者更清楚地说,锁定整个包数据。从另一个线程唤醒select()以返回以便可以操作集合的内容的最佳方法是什么?线程特定的信号?信号?欢迎提出建议。

非常感谢!

编辑:嗯,线程特定的“信号”出来了。如此处所述(http://perldoc.perl.org/threads.html):“相应地,向线程发送信号不会中断线程当前正在处理的操作:信号将在当前操作之后执行已经完成。例如,如果线程卡在 I/O 调用上,向其发送信号不会导致 I/O 调用中断,从而立即执行信号。

这仍然让我想知道select()如果我希望它无限期地阻塞而不是在固定超时后返回,我应该如何处理在线程中唤醒的问题。

4

1 回答 1

2

默认情况下,perl 线程不共享任何数据,因此如果一个线程更改了它的集合,它不会影响另一个。所以是的,它是线程安全的,但它可能不会做你想做的事。

如果您真的想唤醒另一个阻塞选择的线程或进程,一个简单的解决方案是将管道添加到它的读取队列。然后,您可以通过向该管道写入一个字节来唤醒它。

于 2009-06-18T09:49:06.003 回答