Multithreading 阻塞和非阻塞I/O之间的灰色区域?

Multithreading 阻塞和非阻塞I/O之间的灰色区域?,multithreading,jvm,akka,blocking,nonblocking,Multithreading,Jvm,Akka,Blocking,Nonblocking,我熟悉在JVM(Java/nio、Scala/Akka)上根据两种范式(阻塞和非阻塞)进行编程。 然而,我看到中间有一种灰色地带让我困惑 看看你选择的任何非阻塞程序:它充满了阻塞语句 例如,变量的每个赋值都是一个阻塞操作,等待CPU寄存器和内存读取成功。 此外,非阻塞程序甚至包含阻塞语句,这些语句在不违反非阻塞范式的情况下对复杂的内存集合执行计算 与此相反,如果我们以阻塞的方式调用某个外部web服务来接收其结果,则显然违反了非阻塞范式 但在这两个极端之间是什么呢?读/写一个小文件、一个本地套接字

我熟悉在JVM(Java/nio、Scala/Akka)上根据两种范式(阻塞和非阻塞)进行编程。 然而,我看到中间有一种灰色地带让我困惑

看看你选择的任何非阻塞程序:它充满了阻塞语句

例如,变量的每个赋值都是一个阻塞操作,等待CPU寄存器和内存读取成功。 此外,非阻塞程序甚至包含阻塞语句,这些语句在不违反非阻塞范式的情况下对复杂的内存集合执行计算

与此相反,如果我们以阻塞的方式调用某个外部web服务来接收其结果,则显然违反了非阻塞范式

但在这两个极端之间是什么呢?读/写一个小文件、一个本地套接字,或者对嵌入式数据存储引擎(如SQLite、RocksDb等)进行API调用,怎么样。对这些API执行阻塞读/写操作可以吗?他们通常在实践中提供强有力的时间保证(比如 例如,变量的每个赋值都是一个阻塞操作,等待CPU寄存器和内存读取成功

这并不是所谓的“阻塞”。这些操作是恒定时间,与任何IO操作(数千到数十亿个周期之间)的延迟相比,该恒定时间非常低(通常为几个周期)——除了由于内存交换而导致的页面错误,但如果这些操作经常发生,则无论如何都会有问题

如果我们想挑刺,单个指令不会完全阻塞CPU线程,因为现代CPU可以重新排序指令,并在等待内存/缓存或其他更昂贵的指令完成时无序执行没有数据依赖关系的指令

此外,非阻塞程序甚至包含阻塞语句,这些语句在不违反非阻塞范式的情况下对复杂的内存集合执行计算

这些都不被认为是阻止CPU进行工作。如果它们被正确设计为在不阻塞UI的情况下向用户显示结果,那么它们甚至不应该阻止用户交互

对这些API执行阻塞读/写操作可以吗

这始终取决于您首先使用非阻塞方法的原因。您试图解决什么问题?可能一个API保证使用非阻塞方法,而另一个API不保证。
例如,大多数文件IO方法名义上都是阻塞的,但是不使用
fsync
的写入可能非常便宜,特别是如果您不使用spin-rust进行写入,那么在计算线程池中避免使用这些方法可能会有过大的杀伤力。另一方面,在等待多线程时,通常不希望在固定线程池中阻塞线程cond database query

是的。在某些情况下,即使是非I/O纯计算也可能被视为阻塞,例如,某些针对足够大数据块的加密算法。内存分配和释放通常不被视为阻塞,但在实时系统中可能会被视为阻塞。这取决于它们是否会阻止应用程序做一些被认为更重要的事情,他们当然不会阻止CPU工作。不同的抽象级别需要你的答案!但是,“阻止”作为“阻止CPU工作”的技术定义对我来说听起来并不相似。例如,大型“阻止”文件读取也不会阻塞CPU,因为在从hdd到内存的数据传输完成之前,操作系统会切换到另一个线程。AFAIK,在基于JVM的计算框架中,“阻塞与非阻塞”通常意味着等同于“同步与异步控制流”,在语言语句的抽象级别上。阻塞IO确实会阻止CPU在当前执行线程上执行任何进一步的工作。只有在中可以调度其他线程时,才可能进行上下文切换,这不一定总是如此。并且上下文切换不是免费的,因此在poss中使用非阻塞IO也可以避免上下文切换和线程堆栈的成本,实现每阻塞一个线程。这就像并行和并发之间的区别一样,它们是相关的,但并不相同。你问了一个非常广泛的问题。也许我误解了你的意图,因为语言不精确,但如果你在寻求不同的answ,也许你可以澄清一下呃。但我认为我的最后一段适用于任何一种情况。或者它更适合于