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

2018-09-17 14:06:20 +08:00
 ayonel

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

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

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

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

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

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

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

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

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

再进一步,协程又平衡了两种方式,这是题外话。
dychenyi
2018-09-17 15:14:41 +08:00
都没错。
理解的问题。
你的线程是 cpu 密集型。
他的线程是 IO 密集型。
好比你写个 socket server 端,client 端可以连进来,设计成一个线程处理一个 client。 那么最起码能连几百个 client 端就需要几百个线程了。
q397064399
2018-09-17 15:16:19 +08:00
当然可以.. 实际上拿线程池抗压 又不是没干过,因为后端大部分时候 都阻塞在网络 IO 数据库网络 IO 等等上面,
其实实际的计算负载很低的..
catror
2018-09-17 15:16:36 +08:00
看业务场景来决定
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
2018-09-17 15:21:31 +08:00
est
2018-09-17 15:37:36 +08:00
@zsdroid 估计有 200 个都是 idle 的吧。23333
sagaxu
2018-09-17 15:44:30 +08:00
2 倍说的是 running 状态的线程,idle 的不算。运行队列深度不要超过 cpu 核心数的 2 倍,否则会有明显的性能下降。

idle 线程就算有几千个,也不会对性能有很大的影响。业务逻辑大都是同步阻塞模型,堆线程或者进程,十几年前,高校基于 telnet 协议的 bbs,每个在线用户对应一个进程,1 万在线就是 1 万个进程,当年配置很一般的服务器,也能搞定几千在线。
linshuang
2018-09-17 17:19:06 +08:00
1、前面那些拿网络 IO 跟服务器说事的,看看这句话吧——“做一个接口如果用多线程,数量都是 4000 个线程起”。都说是做接口了,明显跟这些玩意基本都不搭噶了,那些东西对他来说都是透明的。
2、万一说他写个接口真的是需要(协调)处理到网络 IO,只能说不愧大厂(啥都从头来),那样确实是需要开很多线程。
3、还有一种就是开线程花很少钱,但往往都是语言层面自带的,语言使用的是用户线程
wysnylc
2018-09-17 19:46:54 +08:00
IO 密集型开 10000 个我觉得也行
xvhfeng
2018-09-18 10:41:16 +08:00
这个问题?哪位同学用的是大型机吗?
线程和进程,基本的问题在于 OS 的支持,一般来说,不管你是 IO 密集型还是 CPU 密集型都不会开到 4000 个线程。就目前互联网企业尿性来说,机器不要说开到 4000 个线程,一般的接口开到 2000 线程都会有点累(注意,我说的是一般的接口)。从 OS 来说,4k 线程上下文的交换可能浪费掉了它原本 80%的性能,有点得不偿失。如果是 IO 密集型操作,完全可以不用走 CPU,应该也用不着 4k 线程来处理这些。如果 IO 密集型不走特殊硬件处理,那么应该也是多线程挂载多 event,然后通过生命周期将其操作拆开,这种方式才相对合理。否则别的请求不是都得饿死吗?
所以,这哥们可能只是酒桌上的一个玩笑,或者......
好吧,还是要回去多看看 OS 的书。

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

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

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

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

© 2021 V2EX