Python学习笔记__10.4章 进程VS线程

# 这是学习廖雪峰老师python教程的学习笔记

1、概览

我们介绍了多进程和多线程,这是实现多任务最常用的两种方式。现在,我们来讨论一下这两种方式的优缺点

要实现多任务,通常我们会设计Master-Worker模式,Master负责分配任务,Worker负责执行任务,因此,多任务环境下,通常是一个Master,多个Worker。

  • 如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker。
  • 如果用多线程实现Master-Worker,主线程就是Master,其他线程就是Worker。

1.1、多进程模式的优缺点

1)优点

稳定性高,因为一个子进程崩溃了,不会影响主进程和其他子进程。(当然主进程挂了所有进程就全挂了,但是Master进程只负责分配任务,挂掉的概率低)

2)缺点

创建进程的代价大,在Unix/Linux系统下,用fork调用还行,在Windows下创建进程开销巨大。另外,操作系统能同时运行的进程数也是有限的,在内存和CPU的限制下,如果有几千个进程同时运行,操作系统连调度都会成问题。

1.2、多线程模式的优缺点

1)优点

多线程模式通常比多进程快一点(只有一点点)。在Windows下,多线程的效率比多进程要高,所以微软的IIS服务器默认采用多线程模式。

2)缺点

致命的缺点就是任何一个线程挂掉都可能直接造成整个进程崩溃,因为所有线程共享进程的内存。由于多线程存在稳定性的问题,IIS的稳定性就不如Apache。

2、进程切换和线程切换

进程切换分两步,线程只做第2步:

  1. 切换页目录以使用新的地址空间
  2. 切换内核栈和硬件上下文。

线程上下文切换和进程上下文切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。

而无论进程/线程切换都要涉及到:

  1. 保存当前执行的现场环境(CPU寄存器状态、内存页等)
  2. 把新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等)

这个切换过程虽然很快,但是也需要耗费时间。如果有几千个任务同时进行,操作系统可能就主要忙着切换任务,根本没有多少时间去执行任务了。所以,多任务一旦多到一个限度,就会消耗掉系统所有的资源,结果效率急剧下降,所有任务都做不好。

3、计算密集型 vs. IO密集型

是否采用多任务的第二个考虑是任务的类型。我们可以把任务分为计算密集型和IO密集型。

3.1、计算密集型

要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

3.2、IO密集型

涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

4、异步IO

考虑到CPU和IO之间巨大的速度差异,一个任务在执行的过程中大部分时间都在等待IO操作,单进程单线程模型会导致别的任务无法并行执行,因此,我们才需要多进程模型或者多线程模型来支持多任务并发执行。

现代操作系统对IO操作已经做了巨大的改进,最大的特点就是支持异步IO。如果充分利用操作系统提供的异步IO支持,就可以用单进程单线程模型来执行多任务,这种全新的模型称为事件驱动模型,Nginx就是支持异步IO的Web服务器,它在单核CPU上采用单进程模型就可以高效地支持多任务。在多核CPU上,可以运行多个进程(数量与CPU核心数相同),充分利用多核CPU。由于系统总的进程数量十分有限,因此操作系统调度非常高效。用异步IO编程模型来实现多任务是一个主要的趋势。

对应到Python语言,单线程的异步编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序。

原文地址:http://blog.51cto.com/12758568/2117005

时间: 2024-12-07 19:15:12

Python学习笔记__10.4章 进程VS线程的相关文章

Android学习笔记—第五章 进程与线程

第五章 进程与线程 进程:一个应用程序就是一个进程 (1)进程的优先级: Foreground Process 前台进程 a. 当前用户正在操作的Activity所在的进程 b. 绑定了当前用户操作的Activity的service所在的进程 c. 通过调用了startForeground()方法提升优先级的service所在的进程 d. 正在调用onCreate().onStart().onDestory()方法的service所在的进程 e. 正在调用onReceiver()方法的Broad

Python学习笔记__10.5章 分布式进程

# 这是学习廖雪峰老师python教程的学习笔记 1.概览 在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上. Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上.依靠网络通信,一个服务进程可以作为调度者,将任务分布到其他多个进程中.由于managers模块封装很好,不必了解网络通信的细节,就可以很

Python学习笔记__10.1章 多进程

# 这是学习廖雪峰老师python教程的学习笔记 1.概览 Unix/Linux操作系统提供了一个fork()系统调用.fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回. 子进程永远返回0,而父进程返回子进程的ID.这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID. 1.1.创建子进程 Python的os模块封装了常见

Python学习笔记__10.3章 ThreadLocal

# 这是学习廖雪峰老师python教程的学习笔记 1.概览 在多线程环境下,每个线程都有自己的数据.一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁.但线程的局部变量,在函数调用时很麻烦 1)方式一:一层一层传 def process_student(name): std = Student(name)   # std是局部变量,但是每个函数都要用它,因此必须传进去: do_task_1(std) do_task_2(std)

APUE学习笔记:第九章 进程关系

9.1 引言 本章将更详尽地说明进程组以及POSIX.1引入的会话的概念.还将介绍登陆shell(登录时所调用的)和所有从登陆shell启动的进程之间的关系. 9.1 终端登陆 系统管理员创建通常名为/etc/ttys的文件,其中每个终端设备都有一行,每一行说明设备名传递给getty程序的参数.当系统自举时,内核创建进程ID为1的进程,依旧是init进程.init进程使系统进入多用户状态.init进程读文件/etc/ttys,对每一个允许登陆的终端设备,init调用一次fork,所生成的子进程则

Python学习笔记__16.2章 TCP编程

# 这是学习廖雪峰老师python教程的学习笔记 Socket是网络编程的一个抽象概念.通常我们用一个Socket表示"打开了一个网络链接",而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可. 1.客户端 大多数连接都是可靠的TCP连接.创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器. 1.1.创建一个基于TCP连接的Socket,获取新浪首页 # 导入socket库: import socket # 创建一个socket,AF_INET

Python学习笔记__2.2章 定义函数

# 这是学习廖雪峰老师python教程的学习笔记 1.定义函数 定义一个函数需要有函数名.参数.函数体.函数体中最好还有 传入的参数判断 1.1.函数创建 定义一个函数用def,数据类型检查用isinstance.例子如下: def my_abs(x): if not isinstance(x, (int, float)):    # 判断传入的参数,是否是 ××× 或 浮点形 raise TypeError('bad operand type')  #  抛出错误 if x >= 0: ret

Python学习笔记__3.3章 列表生成式

# 这是学习廖雪峰老师python教程的学习笔记 1.概览 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式 1.生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] list(range(1, 11)) 2.列表生成式 [1x1, 2x2, 3x3, ..., 10x10] [x*x for x in range(1,11)] 3.使用两层循环 >>>[m + n for m in 'ABC'

Python学习笔记__3.2章 迭代

# 这是学习廖雪峰老师python教程的学习笔记 1.概览 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 当然,不止 list 和 tuple 可以迭代.只要是可迭代对象,无论有无下标,都可以迭代都.包括dict .str .generator 在Python中,迭代是通过for ... in来完成的. 1.1.字典的迭代 # 定义一个字典 d = {'a': 1, 'b': 2, 'c': 3} 迭代 字典