《多线程服务器的适用场合》例释与答疑

本文针对多线程服务器的适用场合进行深入探讨,解释多线程如何影响并发度、吞吐量和响应时间。通过实例,展示了线程池、阻抗匹配原则以及在计算密集型和IO密集型任务中如何利用多线程。此外,还讨论了第三方库使用线程的原因和多线程编程模型的选择,如reactor+线程池和Proactor模式。

陈硕 (giantchen_AT_gmail)

Blog.youkuaiyun.com/Solstice

2010 March 3 - rev 01

 

《多线程服务器的适用场合》(以下简称《适用场合》)一文在博客登出之后,有热心读者提出质疑,我自己也觉得原文没有把道理说通说透,这篇文章试图用一些实例来解答读者的疑问。我本来打算修改原文,但是考虑到已经读过的读者不一定会注意到文章的变动,干脆另写一篇。为方便阅读,本文以问答体呈现。这篇文章可能会反复修改扩充,请注意上面的版本号。

本文所说的“多线程服务器”的定义与前文一样,同时参见《多线程服务器的常用编程模型》(以下简称《常用模型》)一文的详细界定,以下“连接、端口”均指 TCP 协议。

 

1. Linux 能同时启动多少个线程?

对于 32-bit Linux,一个进程的地址空间是 4G,其中用户态能访问 3G 左右,而一个线程的默认栈 (stack) 大小是 10M,心算可知,一个进程大约最多能同时启动 300 个线程。如果不改线程的调用栈大小的话,300 左右是上限,因为程序的其他部分(数据段、代码段、堆、动态库、等等)同样要占用内存(地址空间)。

对于 64-bit 系统,线程数目可大大增加,具体数字我没有测试,因为我实际用不到那么多线程。

以下的关于线程数目的讨论以 32-bit Linux 为例。

 

2. 多线程能提高并发度吗?

如果指的是“并发连接数”,不能。

由问题 1 可知,假如单纯采用 thread per connection 的模型,那么并发连接数最多 300,这远远低于基于事件的单线程程序所能轻松达到的并发连接数(几千上万,甚至几万)。所谓“基于事件”,指的是用 IO multiplexing event loop 的编程模型,又称 Reactor 模式,在《常用模型》一文中已有介绍。

那么采用《常用模型》一文中推荐的 event loop per thread 呢?至少不逊于单线程程序。

小结:thread per connection 不适合高并发场合,其 scalability 不佳。event loop per thread 的并发度不比单线程程序差。

 

3. 多线程能提高吞吐量吗?

对于计算密集型服务,不能。

假设有一个耗时的计算服务,用单线程算需要 0.8s。在一台 8 核的机器上,我们可以启动 8 个线程一起对外服务(如果内存够用,启动 8 个进程也一样)。这样完成单个计算仍然要 0.8s,但是由于这些进程的计算可以同时进行,理想情况下吞吐量可以从单线程的 1.25cps (calc per second) 上升到 10cps。(实际情况可能要打个八折——如果不是打对折的话。)

假如改用并行算法,用 8 个核一起算,理论上如果完全并行,加速比高达 8,那么计算时间是 0.1s,吞吐量还是 10cps,但是首次请求的响应时间却降低了很多。实际上根据 Amdahl's law,即便算法的并行度高达 95%,8 核的加速比也只有 6,计算时间为 0.133s,这样会造成吞吐量下降为 7.5cps。不过以此为代价,换得响应时间的提升,在有些应用场合也是值得的。

这也回答了问题 4。

 

如果用 thread per request 的模型,每个客户请求用一个线程去处理,那么当并发请求数大于某个临界值 T’ 时,吞吐量反而会下降,因为线程多了以后上下文切换的开销也随之增加(分析与数据请见《A Design Framework for Highly Concurrent Systems》 by Matt Welsh et al.)。thread per request 是最简单的使用线程的方式,编程最容易,简单地把多线程程

评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值