Java 事件、线程和Go例程,为什么不使用更多?

Java 事件、线程和Go例程,为什么不使用更多?,java,multithreading,concurrency,jvm,go,Java,Multithreading,Concurrency,Jvm,Go,事件模型和线程模型非常流行,并且经常被讨论 每个I/O操作都可以阻塞的“线程化”方法更简单。编写和调试同步代码更容易,事实上,大多数生态系统都提供阻塞I/O库,只需使用线程池,正确配置它,就可以了 但是。。它无法缩放 然后是“事件”方法,其中有一个线程(或每个cpu一个线程)从不阻塞,只执行cpu指令。当IO返回时,它会激活适当的计算,从而更好地利用CPU 但是。。更难编码,更容易创建不可读的意大利面代码,没有足够的库用于异步I/O等。。。非阻塞和阻塞I/O不能很好地混合。在生态系统中使用它是非

事件模型和线程模型非常流行,并且经常被讨论

每个I/O操作都可以阻塞的“线程化”方法更简单。编写和调试同步代码更容易,事实上,大多数生态系统都提供阻塞I/O库,只需使用线程池,正确配置它,就可以了

但是。。它无法缩放

然后是“事件”方法,其中有一个线程(或每个cpu一个线程)从不阻塞,只执行cpu指令。当IO返回时,它会激活适当的计算,从而更好地利用CPU

但是。。更难编码,更容易创建不可读的意大利面代码,没有足够的库用于异步I/O等。。。非阻塞和阻塞I/O不能很好地混合。在生态系统中使用它是非常有问题的,因为生态系统从一开始就没有设计成无阻塞的。在NodeJS中,所有I/O从一开始就是非阻塞的(因为javascript从一开始就没有I/O库)。希望您能在C++/Java中实现同样的功能。您可以尽最大努力,但需要一个同步调用才能降低性能

然后又来了又走。我最近开始研究Go,因为我发现它的并发模型很有趣。Go提供了“两全其美”的能力,所有的I/O都是阻塞的,编写同步代码,但享受CPU的充分利用

Go对线程有一个抽象,称为“Go例程”,基本上是用户级线程,“Go运行时”(与程序一起编译)负责在实际操作系统线程上调度不同的Go例程(假设每个CPU 1个)每当围棋例程执行系统调用时,“围棋运行时”会安排另一个围棋例程在一个OS线程中运行,它会将围棋例程“多路复用”到OS线程上

用户级线程并不是一个新概念,Go的方法很好,也很简单,所以我开始想,为什么JVM世界不使用类似的抽象,与通常在幕后发生的事情相比,这是儿戏

然后我发现确实如此,Sun的1.2 JVM称它们为绿色线程,这是用户级线程,但这些线程只被多路复用到单个操作系统线程中,它们转向真正的操作系统线程,以允许利用多核CPU



为什么这在1.2之后的JVM世界中不相关?我没有看到Go方法的缺点吗?也许有些概念适用于Go,但在JVM上无法实现?

这是一个非常有趣且质量很好的编写。遗憾的是,它不符合SO的问答模式。关于1.2JVM的绿色线程的说明:它们只是早期的实现;我不相信他们曾经被认为是一个战略上的好方法。让绿色线程作为唯一选项当然是不可取的。进行任何阻止用户级线程的系统调用-你会发现一个缺点。一般来说,这是错误的,Martin。Gosling和Joy(Sun)以及来自英国大学的几位学者讨论过,在Java中可能会引入事件驱动(注意:不是“事件”)CSP模型。乔伊对此很热心,并在博客上发表了自己的看法,但最终高斯林否决了这一想法。当时,“绿色线程”的性能很差,他选择放弃它们而不是采用CSP。不幸的是,他的低风险决策让我们走到了今天