IO :: Select中的select()包装是否是线程安全的?如何解决?

时间:2009-06-18 07:52:01

标签: perl sockets network-programming nonblocking

假设我有一个帖子:

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()的问题。

1 个答案:

答案 0 :(得分:2)

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

如果你真的想要唤醒另一个在select上阻塞的线程或进程,一个简单的解决方案就是在它的读队列中添加一个管道。然后,您可以通过向该管道写入一个字节来唤醒它。