关于 Java 和 go 高并发的话题

2021-07-22 22:45:05 +08:00
 MakHoCheung
go 因为有协程,所以高并发是它的一大优势,但是我看博客,别人说 groutine 的底层也是线程池,这样跟 Java 也一样,为什么 go 在高并发这块就很厉害呢(我不知道 Java 在高并发这块是不是比 go 弱,我没做过什么高并发项目)。发散一下就是 Java 的 NIO +线程池(现实例子就是 netty )跟 go 在高并发这块差距是不是巨大?
6987 次点击
所在节点    问与答
93 条回复
dcalsky
2021-07-22 22:52:14 +08:00
如果底层都是 epoll 那性能都差不多。只不过 goroutine 比较轻量,又有 GMP 帮你调度,关键是还写起来方便心智负担小。

所以总结起来就是:写并发有优势,而不是并发有优势(相对 java )。
caliburn1994
2021-07-22 22:55:48 +08:00
最近看了一些材料。go 协程比 Java 得线程好,我觉得主要是 Java 堵塞就是堵塞了,一个 goroutine 堵塞了就会启动切换到另外一个 goroutine
ihipop
2021-07-22 22:55:49 +08:00
go 用线程来管理和执行一个或者多个协程,开 1w 协程无需 1w 线程。
MakHoCheung
2021-07-22 22:59:29 +08:00
@ihipop 问题是干一件事,开 1w 个协程干和 Java 用线程数池干,协程更加高效更快?
MakHoCheung
2021-07-22 23:00:29 +08:00
@dcalsky 这个回答可以的
caliburn1994
2021-07-22 23:01:36 +08:00
另外一点,Java 使用的是 user thread,而 goroutine 使用的是 green thread,green thread 的依赖是 user thread 。越靠近底层 context switch 成本越大。

Java 的 green thread 是 Loom,还在发展中。
MakHoCheung
2021-07-22 23:03:30 +08:00
@caliburn1994 这个怎么做到的呢?堵塞的 goroutine 和切换的新的 goroutine 在底层也是两个不同的线程吧,一个在等 io 一个在运行
ihipop
2021-07-22 23:07:22 +08:00
@MakHoCheung 自然是的,至少协程没有线程切换 /系统中断开销,开 1w 协程切换开销远远小于 1w 线程,协程比线程轻量的多自然服务能力也可以同步提升。
caliburn1994
2021-07-22 23:11:05 +08:00
@MakHoCheung goroutine 不是线程,而且网上说它是一个复杂的协程。切换的问题就涉及 preemption (抢占),goroutine 现在是 asynchronous preemption (异步抢占)


等 IO 的那个算是异步的问题。


(我也在自学中~)
MakHoCheung
2021-07-22 23:23:31 +08:00
@ihipop 你误会我的意思了,我的意思是 1w 协程 VS 线程池( 4 条线程),假如 1 个线程里面有 2500 个协程,那 1w 个协程全部切换个遍,底层也要线程切换的吧。另外又延伸一下,2 个 goroutine 进行 2 个 http 请求里面要不要线程切换?
MakHoCheung
2021-07-22 23:30:45 +08:00
@ihipop 还有个我不太懂的地方,有什么场景下,2 条 goroutine 同时进行的一样的操作,底层是不需要线程切换的
caliburn1994
2021-07-22 23:34:00 +08:00
建议从 Java 的 1.2 版本的为什么放弃 green thread 开始看,挺有趣的
iyaozhen
2021-07-23 00:00:45 +08:00
"别人说 groutine 的底层也是线程池" 这个不太对吧

“假如 1 个线程里面有 2500 个协程,那 1w 个协程全部切换个遍,底层也要线程切换的吧” 不用呀,简单来说,第一个线程里面 2500 个协程自己切换,不用切换线程。

go 的优势是,第一个线程里面有个协程卡了,剩下的 2499 个协程可以调度到另一个线程上去
MakHoCheung
2021-07-23 00:29:43 +08:00
@iyaozhen “第一个线程里面有个协程卡了,剩下的 2499 个协程可以调度到另一个线程上去”这里不就有线程上下文切换了吗
MakHoCheung
2021-07-23 00:31:02 +08:00
@iyaozhen groutine 的底层也是线程池,这个我看博客的,我不是很懂 goroutine
wellsc
2021-07-23 00:42:57 +08:00
@dcalsky 并发还得看你是 io 密集还是 cpu 密集呢,不够严谨
ccde8259
2021-07-23 01:06:50 +08:00
@MakHoCheung
发生的是协程上下文切换?
Leviathann
2021-07-23 01:19:42 +08:00
主要是 go 写并发程序的心智负担小,且 go 编译后为机器码
听说 loom 的目标也是类似这种,再加上 graalvm 的 aot 编译,以后应该会差不太多
不过离正式支持 loom 的 lts 版本 jdk 估计还得等个几年。。
sutra
2021-07-23 01:31:21 +08:00
Servlet 3.0, 3.1 有 Async 、NIO 之类的支持。
btnokami
2021-07-23 01:53:11 +08:00
协程是在 user space 切换,线程要从 user space 切到 kernel space,开销不一样的。而且线程要在 memory 里自己新建 stack,协程是共享的 stack

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/791169

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX