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

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

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

  • 模式 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. WEKA使用教程(经典教程转载)

    http://blog.csdn.net/yangliuy/article/details/7589306 WEKA使用教程(经典教程转载) 标签: lift算法csv数据挖掘class任务 2012 ...

  2. Delphi的指针(转)

    源:http://blog.csdn.net/henreash/article/details/7368088 Pointers are like jumps, leading wildly from ...

  3. 程序ajax请求公共组件-- app-jquery-http.js

    $.HTTP = { getUrlParam : function (name) { var reg = new RegExp ("(^|&)" + name + &quo ...

  4. PHP 领域逻辑与数据库映射

    http://blog.csdn.net/hguisu/article/details/7569968

  5. hibernate和ibatis的区别

    通过别人的资料,进行自己关注的一些扼要点的整理 共同点: 1. 不同点:1. 自动化程度上,hibernate是全自动化的orm框架,提供了对象到数据库的完全映射和sql的内部自动生成,其对象映射是指 ...

  6. java丢手帕 约瑟夫问题

    一.问题描述:     n个人围成一个圈,编号为1~n,从第一号开始报数,报到3的倍数的人离开,一直数下去,直到最后只有一个人,求此人编号. 二.问题提示:  使用一维数组,数组元素初始为1,从1开始 ...

  7. 四、Hbase

    一.什么情况下使用Hbase 例子: 这里Order By无时不刻的处理,我们要看到刚才的足迹,不能使用缓存技巧. 根据时间戳来查询,显然很快,应为Hbase就是以时间戳来存的. 将最近的数据放在内存 ...

  8. VSC#2010打开视图编辑器假死/卡死

    最近写项目代码的时候写C#,VSC#2010刚配置好,打开之前同学写的项目的设计界面结果...我擦,卡死了,重复几次都是这样. 于是上网搜发现是VS一个bug,打一个VSSP1补丁就好了~ http: ...

  9. MySQL的char和varchar

    一.VARCHAR与CHAR字符型数据的差异 在MySQL数据库中,用的最多的字符型数据类型就是Varchar和Char,这两种数据类型虽然都是用来存放字符型数据,但是无论从结构还是从数据的保存方式来 ...

  10. LPC1788的IIC使用

    #ifndef __IIC0_H_ #define __IIC0_H_ #include "common.h" #include "delay.h" //IIC ...