在选择器线程之外的其他线程中设置 SelectionKey 的 interestOps 是否安全? (Java 仁王)

Is it safe to set interestOps of SelectionKey in other thread than selector thread? (Java Nio)

我看过很多JavaNio的例子。都是在selector线程中设置SelectionKey的interestOps。

他们为什么这样做? 在选择器线程之外的其他线程中设置 SelectionKey 的 interestOps 是否安全?

或者有可能出现不正常的情况,他们就做了?

SelectionKey JavaDoc 是这样说的:

The operations of reading and writing the interest set will, in general, be synchronized with certain operations of the selector. Exactly how this synchronization is performed is implementation-dependent: In a naive implementation, reading or writing the interest set may block indefinitely if a selection operation is already in progress; in a high-performance implementation, reading or writing the interest set may block briefly, if at all.

结合墨菲定律,它实际上保证你只会遇到 "naïve" 实现,所以安全总比抱歉好,只在选择器线程中使用感兴趣的操作,保证它们不会块。

Is it safe to set interestOps of SelectionKey in other thread than selector thread

所谓安全,我猜你指的是多线程安全。
答:是的。其实很常见(不知道你看的是什么NIO代码)

Or there are abnormal situations that can occur, so they do it?

一个。是的,具体来说,它 可能 阻塞 iff​​ select 或线程处于阻塞 select() 调用
现在,在大多数情况下,这不是一个实际问题,因为对于繁忙的服务器 select() 立即调用 return(或多或少)
为什么?因为总是至少有一个 Channel 有字节要读取
问题是,即使是繁忙的服务器也不总是很忙(比如 2:00 am),在这种情况下,Reader 线程(不是 Selector 线程)理论上可能会永远阻塞(这是一个竞争条件)
所以有一些实践可以减轻(虽然不是消除)竞争条件:

  1. 让选择器线程始终使用定时 select(长毫秒)调用
  2. 有 Reader 个线程:

    key.selector().wakeup()
    key.interestOps(SelectionKey.OP_READ)
    

这实际上使得 Reader 线程极不可能阻塞很长时间

坦率地说,这并不理想(不应允许 IMO interestOps() 阻塞),但比替代方案更好