【问题标题】:Is the select() wrapper in IO::Select thread-safe? How to work around?IO::Select 中的 select() 包装器是线程安全的吗?如何解决?
【发布时间】:2009-06-18 07:52:01
【问题描述】:

假设我有一个线程:

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

【问题讨论】:

    标签: perl sockets network-programming nonblocking


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-31
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      • 1970-01-01
      • 2011-06-13
      • 1970-01-01
      相关资源
      最近更新 更多