Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于IO多路复用为什么搭配非阻塞IO? #482

Closed
jinshuai86 opened this issue Dec 5, 2018 · 6 comments
Closed

关于IO多路复用为什么搭配非阻塞IO? #482

jinshuai86 opened this issue Dec 5, 2018 · 6 comments
Labels
question 提问

Comments

@jinshuai86
Copy link

  • 关于Java IO介绍NIO的一段:“ 通过配置监听的通道 Channel 为非阻塞,那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待,而是继续轮询其它 Channel,找到 IO 事件已经到达的 Channel 执行。”
  • 我觉得配置SocketChannel为非阻塞是为了在IO复用第二阶段(copy data from kernel to user) 使得对socket的操作是非阻塞。
  • Linux对于select()为什么搭配非阻塞IO使用: Under Linux, select() may report a socket file descriptor as “ready for reading”, while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block. 我理解的是如果socket配置为阻塞,当socket可用后,内核会校验socket的数据,如果校验错误会丢弃这些数据,而此时调用read()由于没有数据了会阻塞当前线程。相反的是如果配置为非阻塞就不会阻塞当前线程。
  • 那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待” 我觉得Channel对应的IO事件没有发生时,调用select()会一直阻塞线程,即使配置Channel为非阻塞。
  • 参考了知乎的一个回答:链接
  • 望大佬解惑😭
@CyC2018
Copy link
Owner

CyC2018 commented Dec 6, 2018

@jinshuai86

Java NIO 被称为非阻塞 IO,这是与传统的 BIO(阻塞 IO)相对的。BIO 执行 accept 等操作时会一直阻塞,而 NIO 不会阻塞。只要理解了 Reactor 模型就能理解这里的非阻塞意义。

上面的 select 文档提到的非阻塞用途和这里的不太一样。

@jinshuai86
Copy link
Author

  • 谢谢大佬回复。不过还是不太明白这句话 “通过配置监听的通道 Channel 为非阻塞,那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待,而是继续轮询其它 Channel,找到 IO 事件已经到达的 Channel 执行。” 主要不太明白socketChannel.configureBlocking(false)的目的。大佬的意思是为了在select()轮询Channel时,如果Channel不可用时不会阻塞当前线程吗? 还是不会阻塞XXX?这里不太清楚😭
  • 我理解的socketChannel.configureBlocking(false)目的是为了搭配非阻塞IO使用。当调用Selecor的select(),尽管设置了非阻塞(socketChannel.configureBlocking(false)),但是当注册的事件没发生时还是会一直阻塞当前线程。
  • 关于这个函数的介绍文档:链接
    • block - If true then this channel will be placed in blocking mode; if false then it will be placed non-blocking mode
  • 关于函数介绍中提到的blocking mode文档介绍:链接,里面提到了通过设置非阻塞可以在I/O Operation时不阻塞当前线程,我理解的I/O Operation是把数据从内核态拷贝到用户态的过程,此时如果内核态丢弃数据导致没有了数据而不会阻塞线程就是select手册里提到的更安全一些?
    • Blocking mode
      • A selectable channel is either in blocking mode or in non-blocking mode. In blocking mode, every I/O operation invoked upon the channel will block until it completes. In non-blocking mode an I/O operation will never block and may transfer fewer bytes than were requested or possibly no bytes at all. The blocking mode of a selectable channel may be determined by invoking its isBlocking method.
      • Newly-created selectable channels are always in blocking mode. Non-blocking mode is most useful in conjunction with selector-based multiplexing. A channel must be placed into non-blocking mode before being registered with a selector, and may not be returned to blocking mode until it has been deregistered.
  • 另外看了个关于select的博客,我理解的是当前线程调用select以后,好像就不是在当前线程对应的内核态去执行(轮询Channel),而是通过内核态其它线程执行?链接。有点转不过弯来😭

@CyC2018
Copy link
Owner

CyC2018 commented Dec 6, 2018

@jinshuai86

Non-blocking mode is most useful in conjunction with selector-based multiplexing.

这里的非阻塞特性允许一个线程处理多个 Channel,而传统的 BIO 一个线程只能处理一个 Channel。

我理解的 I/O Operation 是把数据从内核态拷贝到用户态的过程

你理解感觉不对,这里的非阻塞描述的是第一个阶段,而 select 文档那里写的非阻塞描述的是第二个阶段。

@jinshuai86
Copy link
Author

谢谢大佬,之前理解的IO复用第一阶段(调用select()直到有可用socket)一直会阻塞当前线程,然后在第二阶段(copy data from kernel to user)如果socket设置了非阻塞,在内核没有数据时(就像select手册里说的由于检验错误丢弃了已经准备好的数据)进行I/O operation 不会阻塞当前线程。我理解应该有问题,我再去查查资料😄😄

@CyC2018
Copy link
Owner

CyC2018 commented Dec 7, 2018

@jinshuai86 IO 多路复用在第一阶段既可以说成是阻塞,也可以说成是非阻塞,就看从哪方面去考虑。

@makeghyours
Copy link

هل تدعم العربية

@CyC2018 CyC2018 closed this as completed Dec 8, 2018
@CyC2018 CyC2018 added the question 提问 label Feb 24, 2019
@CyC2018 CyC2018 reopened this Feb 25, 2019
@CyC2018 CyC2018 closed this as completed Jun 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question 提问
Projects
None yet
Development

No branches or pull requests

3 participants