V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ayonel
V2EX  ›  Java

请教各位大佬一个关于多线程的问题, RZ

  •  
  •   ayonel · 2018-09-17 14:06:20 +08:00 · 2884 次点击
    这是一个创建于 2019 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近跟一个同事聊天时,同事说之前在某 BAT 大厂实习后台开发时,做一个接口如果用多线程,数量都是 4000 个线程起,我对此表示怀疑。因为据我的认知,线程数量一般开到 CPU 核心数最好,最好不要超过 2 倍 CPU 核心数。因此,想请教下给为大佬,实际生产中用到的高并发的情况,真的能开这么多线程吗?

    21 条回复    2018-09-20 11:57:55 +08:00
    Tinet
        1
    Tinet  
       2018-09-17 14:08:41 +08:00
    你确定他说的不是协程
    lirau
        2
    lirau  
       2018-09-17 14:19:03 +08:00
    reus
        3
    reus  
       2018-09-17 14:21:32 +08:00
    可能说的是集群分配给这个接口的数量吧,单机开这么多没意义。
    dingzs3
        4
    dingzs3  
       2018-09-17 14:24:34 +08:00
    这个估计就是不靠谱的,单机如果线程数过多,会产生太多的上下文切换开销和调度的开销,还有就是如果 cpu 迁移导致的缓存失效代价。
    lhy360121
        5
    lhy360121  
       2018-09-17 14:24:40 +08:00
    能。

    和 cpu 核心数一致的或 2 倍的应该是进程,不是线程。

    高配的机器可以开到几百或上千的线程。

    还和开发语言和业务场景有过。
    chocotan
        6
    chocotan  
       2018-09-17 14:31:16 +08:00
    看是 cpu 密集还是 io 密集
    zzj0311
        7
    zzj0311  
       2018-09-17 14:32:39 +08:00 via Android   ❤️ 1
    @lhy360121 你家电脑只有十几个进程的么😂
    lhy360121
        8
    lhy360121  
       2018-09-17 14:36:48 +08:00
    @zzj0311 你家的几十个进程一致在跑吗? 高并发的进程那是一直在跑,多开进程没有意义。

    一看你就没开发过服务端的程序。

    你家电脑和服务器器是一样的吗 ? 也就知道个 windows 了。
    georgetso
        9
    georgetso  
       2018-09-17 14:43:18 +08:00
    xylophone21
        10
    xylophone21  
       2018-09-17 14:52:51 +08:00
    粗略来说,你的认知没错,但有前提。

    其前提是(类似) Nginx 中的那种异步模型,这种方式下,一个线程(进程)可以服务多个请求,由于每个线程实际上都很忙,所以超过 CPU 个数太多反而不好,增加上下文切换的消耗。这种方式性能很高,但代码写起来困难,因为相当于你手工处理了操作体统上下文切换的事情,但处理的不那么特化,只适应当前一种场景。

    在这种模型出现之前,流行的是多线程 /进程模型,一个线程 /进程为一个连接服务,每个线程大多数时候都在等待 IO,所以开的比 CPU 核心数多的多也没关系,也不得不开。这样的代码写起来非常简单,因为操作系统帮你隔离了每个请求之间的上下文切换,但性能就差一些,因为这种上下文切换很重,很通用,做了超出预期的事。

    再进一步,协程又平衡了两种方式,这是题外话。
    dychenyi
        11
    dychenyi  
       2018-09-17 15:14:41 +08:00
    都没错。
    理解的问题。
    你的线程是 cpu 密集型。
    他的线程是 IO 密集型。
    好比你写个 socket server 端,client 端可以连进来,设计成一个线程处理一个 client。 那么最起码能连几百个 client 端就需要几百个线程了。
    q397064399
        12
    q397064399  
       2018-09-17 15:16:19 +08:00
    当然可以.. 实际上拿线程池抗压 又不是没干过,因为后端大部分时候 都阻塞在网络 IO 数据库网络 IO 等等上面,
    其实实际的计算负载很低的..
    catror
        13
    catror  
       2018-09-17 15:16:36 +08:00 via Android
    看业务场景来决定
    Allianzcortex
        14
    Allianzcortex  
       2018-09-17 15:20:45 +08:00
    @xylophone21 @lhy360121 @ayonel 我理解的 [线程数量一般开到 CPU 核心数最好,最好不要超过 2 倍 CPU 核心数] 这句话的产生是因为 Intel 可以让一个实体 CPU 模拟出两倍逻辑 CPU...但具体使用场景里线程数量应该没有什么固定的 best pramater,参考 https://www.quora.com/How-can-I-tell-how-many-processes-are-too-many-on-a-Linux-machine 里的回答, [Linux scales very well with the number of processes on a system, Thus there isn't a definitive answer to how many processes are "too many." ] ,所以系统目标是 system load 要小,这个时候 number of processes 只是一个考量因素,memory 与 I/O bandwidth 也算,就需要不断调优数值,和 @chocotan 说的 CPU-bound 还是 I/O-bound 系统有很大关系。但线程最大值不会超过 $kernel.pid_max。如果有不对的话麻烦大家指出来改一下哈😄
    zsdroid
        15
    zsdroid  
       2018-09-17 15:21:31 +08:00
    est
        16
    est  
       2018-09-17 15:37:36 +08:00
    @zsdroid 估计有 200 个都是 idle 的吧。23333
    sagaxu
        17
    sagaxu  
       2018-09-17 15:44:30 +08:00 via Android
    2 倍说的是 running 状态的线程,idle 的不算。运行队列深度不要超过 cpu 核心数的 2 倍,否则会有明显的性能下降。

    idle 线程就算有几千个,也不会对性能有很大的影响。业务逻辑大都是同步阻塞模型,堆线程或者进程,十几年前,高校基于 telnet 协议的 bbs,每个在线用户对应一个进程,1 万在线就是 1 万个进程,当年配置很一般的服务器,也能搞定几千在线。
    linshuang
        18
    linshuang  
       2018-09-17 17:19:06 +08:00
    1、前面那些拿网络 IO 跟服务器说事的,看看这句话吧——“做一个接口如果用多线程,数量都是 4000 个线程起”。都说是做接口了,明显跟这些玩意基本都不搭噶了,那些东西对他来说都是透明的。
    2、万一说他写个接口真的是需要(协调)处理到网络 IO,只能说不愧大厂(啥都从头来),那样确实是需要开很多线程。
    3、还有一种就是开线程花很少钱,但往往都是语言层面自带的,语言使用的是用户线程
    wysnylc
        19
    wysnylc  
       2018-09-17 19:46:54 +08:00
    IO 密集型开 10000 个我觉得也行
    xvhfeng
        20
    xvhfeng  
       2018-09-18 10:41:16 +08:00
    这个问题?哪位同学用的是大型机吗?
    线程和进程,基本的问题在于 OS 的支持,一般来说,不管你是 IO 密集型还是 CPU 密集型都不会开到 4000 个线程。就目前互联网企业尿性来说,机器不要说开到 4000 个线程,一般的接口开到 2000 线程都会有点累(注意,我说的是一般的接口)。从 OS 来说,4k 线程上下文的交换可能浪费掉了它原本 80%的性能,有点得不偿失。如果是 IO 密集型操作,完全可以不用走 CPU,应该也用不着 4k 线程来处理这些。如果 IO 密集型不走特殊硬件处理,那么应该也是多线程挂载多 event,然后通过生命周期将其操作拆开,这种方式才相对合理。否则别的请求不是都得饿死吗?
    所以,这哥们可能只是酒桌上的一个玩笑,或者......
    好吧,还是要回去多看看 OS 的书。
    ayonel
        21
    ayonel  
    OP
       2018-09-20 11:57:55 +08:00
    多谢各位大佬的回复,受益匪浅
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3211 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 11:37 · PVG 19:37 · LAX 04:37 · JFK 07:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.