本文共 2487 字,大约阅读时间需要 8 分钟。
本章作者主要是总结了一两种常用的线程模型。归纳了进程通信与线程同步的最佳实践
进程与线程的区别:
单线程服务器的常用编程模型
在高性能网络程序中,使用的最广泛的是“non-blocking IO + multiplexing IO”这种模型,即reactor模式。
在non-blocking IO + multiplexing IO 模型中,程序的主要结构是一个事件循环。以事件驱动和事件回调的方式实现业务逻辑。Reactor模型优点编写简单,效率不错,对于IO密集型应用是一个不错选择。但是它也有其本质的缺点:它要求事件的回调函数必须是非阻塞的,而且对于网络IO的请求相应协议,它容易割裂业务逻辑,使其散布与多个回调函数之间。
多线程服务器的常用编程模型
多线程的服务器编程模型主要有以下四种:
muduo中主要采用的是第三种来编写多写成网络服务程序。即 non-blocking + one loop per thread。
non-blocking + one loop per thread
在这种模型下,程序里的每个IO线程都有一个event loop,用于处理读写事件。这种方式有以下好处:
IO事件发生的线程是固定的,同一个TCP不需要考虑事件并发。
线程池
对于没有IO而光有计算任务的线程,使用event loop有点浪费。一般用blocking quene的方法来实现任务队列。除了任务队列,还可以用BlockingQuene实现数据的生产者消费者队列,即T是数据类型而不是函数类型。推荐模式
muduo推荐的C++多线程服务器编程模式为:one (event) loop per thread + thread pool。其中进程间通信只用TCP
进程间通信包含下面的模式:
进程间通信muduo主要选择socket。好处在于:
多线程服务器的适用场合
开发服务器程序的基本任务是处理并发连接,服务端处理网络并发连接主要有下面两种方式
为了充分利用硬件资源,本书主要采用后一种方式。下面需要解决的问题是:多个线程是应该属于一个进程,还是分属于多个进程?
首先,如果要在一台机器上提供一种服务或者执行一个任务,可用的模式有:
可以对这些模式做以下总结:
模式3是公认的主流模式,它有以下两个子模式
模式2 是被很多人鄙视的,因为多线程程序难写,而且与3相比没有什么优势
下面主要讨论模式3和模式2的优劣
问题主要是:什么时候一个服务器程序应该用多线程编写??必须使用单线程的场合
只有单线程的程序才能fork。而且单线程程序能限制CPU的占有率(无论如何,它都只占用一个core,如果多线程的话,可能会把多个核都占满),避免过分抢占系统资源。
单线程的优缺点
单线程程序编程简单,但是由于eventloop的非抢占式,单线程可能会造成优先级反转(P70)。这个缺点可以由多线程来克服。
其实在性能上,多线程没有绝对的优势。因为如果很少的CPU负载能让IO慢跑,那多线程是没啥用处的,而且即使是在CPU满跑的情况下,选用模式3a应该是最合适的。
综上,多线程几乎没有什么优势
适用于多线程的场景
一个多线程程序中线程主要分为以下几类
多线程和单线程多进程的取舍
在其他条件相同的情况下,可以根据工作集的大小来选择
工作集:服务程序响应一次请求所访问的内存大小。
如果工作集较大,那么就用多线程,避免CPU cache换入换出,影响性能。否则就用单线程多进程,享受单线程编程的便利。
转载地址:http://wsqxi.baihongyu.com/