专栏名称: 聊聊架构
聊聊架构
目录
相关文章推荐
美团技术团队  ·  可信实验白皮书系列03:随机对照实验 ·  2 天前  
架构师之路  ·  爸爸!除了你,沈括,沈万三... ... ·  3 天前  
51好读  ›  专栏  ›  聊聊架构

为什么能有上百万个Goroutines,却只能有上千个Java线程?

聊聊架构  · 公众号  · 架构  · 2018-07-21 21:32

正文

请到「今天看啥」查看全文


  • 一个栈。也就是,我当前的状态是什么?栈中包含了本地变量以及指向变量所分配的堆的指针。同一个进程中的所有线程共享相同的堆 [2]。

  • 鉴于以上两点,系统在将线程调度到 CPU 上时就有了足够的信息,能够暂停某个线程、允许其他的线程运行,随后再次恢复原来的线程。这种操作通常对线程来说是完全透明的。从线程的角度来说,它是连续运行的。线程能够感知到重新调度的唯一方式是测量连续操作之间的计时 [3]。

    回到我们最原始的问题:我们为什么能有这么多的 Goroutines 呢?

    JVM 使用操作系统线程

    尽管并非规范所要求,但是据我所知所有的现代、通用 JVM 都将线程委托给了平台的操作系统线程来处理。在接下来的内容中,我将会使用“用户空间线程(user space thread)”来代指由语言进行调度的线程,而不是内核 /OS 所调度的线程。操作系统实现的线程有两个属性,这两个属性极大地限制了它们可以存在的数量;任何将语言线程和操作系统线程进行 1:1 映射的解决方案都无法支持大规模的并发。

    在 JVM 中,固定大小的栈

    使用操作系统线程将会导致每个线程都有固定的、较大的内存成本

    采用操作系统线程的另一个主要问题是每个 OS 线程都有大小固定的栈。尽管这个大小是可以配置的,但是在 64 位的环境中,JVM 会为每个线程分配 1M 的栈。你可以将默认的栈空间设置地更小一些,但是你需要权衡内存的使用,因为这会增加栈溢出的风险。代码中的递归越多,就越有可能出现栈溢出。如果你保持默认值的话,那么 1000 个线程就将使用 1GB 的 RAM。虽然现在 RAM 便宜了很多,但是几乎没有人会为了运行上百万个线程而准备 TB 级别的 RAM。







    请到「今天看啥」查看全文