如果要在一台多核机器上提供一种服务或执行一个任务,可用的模式有

  • 运行一个单线程的进程
  • 运行一个多线程的进程
  • 运行多个单线程的进程
  • 运行多个多线程的进程

这些模式之间的比较已经是老生常谈,简单地总结

  • 模式 1 是不可伸缩的 (scalable),不能发挥多核机器的计算能力;
  • 模式 3 是目前公认的主流模式。它有两种子模式:
    3a 简单地把模式 1 中的进程运行多份,如果能用多个 tcp port 对外提供服务的话;
    3b 主进程+woker进程,如果必须绑定到一个 tcp port,比如 httpd+fastcgi。
  • 模式 2 是很多人鄙视的,认为多线程程序难写,而且不比模式 3 有什么优势;
  • 模式 4 更是千夫所指,它不但没有结合 2 和 3 的优点,反而汇聚了二者的缺点。

据我所知,有两种场合必须使用单线程

  • 程序可能会 fork()。
  • 限制程序的 CPU 占用率。

单线程程序的优缺点

  • event loop 有一个明显的缺点,它是非抢占的(non-preemptive)。假设事件 a 的优先级高于事件 b,处理事件 a 需要 1ms,处理事件 b 需要 10ms。如果事件 b 稍早于 a 发生,那么当事件 a 到来时,程序已经离开了 poll() 调用开始处理事件 b。事件 a 要等上 10ms 才有机会被处理,总的响应时间为 11ms。这等于发生了优先级反转。这可缺点可以用多线程来克服,这也是多线程的主要优势。
  • 如果用很少的 CPU 负载就能让的 IO 跑满,或者用很少的 IO 流量就能让 CPU 跑满,那么多线程没啥用处。

多线程的适用场景

  • 提高响应速度,让 IO 和“计算”相互重叠,降低 latency。虽然多线程不能提高绝对性能,但能提高平均响应性能。

模式 2 和模式 3a 该如何取舍
如果工作集较大,那么就用多线程,避免 CPU cache 换入换出,影响性能;否则,就用单线程多进程,享受单线程编程的便利。

一个程序要做成多线程的,大致要满足

  • 有多个 CPU 可用。单核机器上多线程的优势不明显;
  • 线程间有共享数据。如果没有共享数据,用模型 3b 就行。虽然我们应该把线程间的共享数据降到最低,但不代表没有;
  • 共享的数据是可以修改的,而不是静态的常量表。如果数据不能修改,那么可以在进程间用 shared memory,模式 3 就能胜任;
  • 提供非均质的服务。即,事件的响应有优先级差异,我们可以用专门的线程来处理优先级高的事件。防止优先级反转;
  • latency 和 throughput 同样重要,不是逻辑简单的 IO bound 或 CPU bound 程序;
  • 利用异步操作。比如 logging。无论往磁盘写 log file,还是往 log server 发送消息都不应该阻塞 critical path;
  • 能 scale up。一个好的多线程程序应该能享受增加 CPU 数目带来的好处,目前主流是 8 核,很快就会用到 16 核的机器了;
  • 具有可预测的性能。随着负载增加,性能缓慢下降,超过某个临界点之后急速下降。线程数目一般不随负载变化;
  • 多线程能有效地划分责任与功能,让每个线程的逻辑比较简单,任务单一,便于编码。而不是把所有逻辑都塞到一个 event loop 里,就像 Win32 SDK 程序那样。

一个多线程服务程序中的线程大致可分为 3 类

  • IO 线程,这类线程的的主循环是 io multiplexing,等在 select/poll/epoll 系统调用上。这类线程也处理定时事件。当然它的功能不止 IO,有些计算也可以放入其中;
  • 计算线程,这类线程的主循环是 blocking queue,等在 condition variable 上。这类线程一般位于 thread pool 中;
  • 第三方库所用的线程,比如 logging,又比如 database connection。

参考:《Linux多线程服务端编程》。

《Linux多线程服务端编程》笔记——多线程服务器的适用场合的更多相关文章

  1. 《Linux多线程服务端编程》笔记——线程同步精要

    并发编程基本模型 message passing和shared memory. 线程同步的四项原则 尽量最低限度地共享对象,减少需要同步的场合.如果确实需要,优先考虑共享 immutable 对象. ...

  2. Linux多线程服务端编程一些总结

    能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...

  3. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  4. 一、智能指针及线程同步总结------linux多线程服务端编程

    更新2.0 二.多线程及服务器编程总结------linux多线程服务端编程 https://www.cnblogs.com/l2017/p/11335609.html 三.分布式编程总结------ ...

  5. 《Linux 多线程服务端编程:使用 muduo C++ 网络库》电子版上市

    <Linux 多线程服务端编程:使用 muduo C++ 网络库> 电子版已在京东和亚马逊上市销售. 京东购买地址:http://e.jd.com/30149978.html 亚马逊Kin ...

  6. 《Linux多线程服务端编程——使用muduo C++网络库》读书笔记

    第一章 线程安全的对象生命期管理 第二章 线程同步精要 第三章 多线程服务器的适用场合与常用编程模型 第四章 C++多线程系统编程精要 1.(P84)11个常用的最基本Pthreads函数: 2个:线 ...

  7. Linux多线程服务端编程:使用muduo C++网络库

    内容推荐本 书主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread.这 ...

  8. Linux多线程服务端编程 使用muduo C++网络库 学习笔记 日志log

    代码来自陈硕开源代码库 muduo中 地址是https://github.com/chenshuo/muduo #pragma once #include <string> #define ...

  9. 二、多线程及服务器编程总结------linux多线程服务端编程

随机推荐

  1. 用css、html编写一个两列布局的网页,名称为css.html ,要求左侧宽度为200px ,右侧自动扩展

    <body><div style=" float:left; width:200px; height:300px; border: 1px #0033FF solid;&q ...

  2. php 内置的 webserver 研究。

    今天,试了一下通过 php5.4.45 内置的webserver , 在Windows XP 上面能够跑起公司的一个项目,完全无压力.哈哈,只要一个php 就可以,不需要 Apache , Nginx ...

  3. java如何计算程序运行时间

    long startTime = System.currentTimeMillis();    //获取开始时间 doSomething();    //测试的代码段 long endTime = S ...

  4. 根据XPATH去查看修改xml文件节点的内容

    首先给出xml文件解析的路径,然后去读取节点的内容. package com.inetpsa.eqc.threads; import java.util.List; import java.io.Fi ...

  5. HMM的概率计算问题和预测问题的java实现

    HMM(hidden markov model)可以用于模式识别,李开复老师就是采用了HMM完成了语音识别. 一下的例子来自于<统计学习方法> 一个HMM由初始概率分布,状态转移概率分布, ...

  6. Android L(5.0)源码之图形与图像处理之简单图片——Bitmap

    最近在研究android 5.0的gallery模块,学习了相关的知识点,准备写点博客总结一下,有时间了会补充完整

  7. jQuery EasyUI学习资源汇总

    jQuery EasyUI学习资源汇总 EasyUi – 1.入门 EasyUi – 2.布局Layout + 3.登录界面 EasyUi – 4.datwagrid 学习Jquery EasyUI的 ...

  8. CentOS6.5安装python redis模块

    1.下载安装包https://pypi.python.org/packages/source/r/redis/redis-2.10.3.tar.gz 2.解压tar -zxf redis-2.10.3 ...

  9. vuejs 父组件向子组件传递($broadcast()的用法)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. CentOS根分区占满

    我中奖了!!! 查看硬盘的使用情况(bjchenxu)df -k 以K为单位显示df -h 以人性化单位显示,可以是b,k,m,g,t.. 查看各目录占用大小 du -sh * du -ms /*