一、IO多路复用
1 | 1.阻塞I/O模型 |
如果一个I/O流进来,我们就开启一个进程处理这个I/O流。那么假设现在有一百万个I/O流进来,那我们就需要开启一百万个进程一一对应处理这些I/O流(——这就是传统意义下的多进程并发处理)。思考一下,一百万个进程,你的CPU占有率会多高,这个实现方式及其的不合理。所以人们提出了I/O多路复用这个模型,一个线程,通过记录I/O流的状态来同时管理多个I/O,可以提高服务器的吞吐能力。
I/O multiplexing 也就是我们所说的I/O多路复用,但是这个翻译真的很不生动,所以我更喜欢将它拆开,变成 I/O multi plexing。multi意味着多,而plex意味着丛(丛:聚集,许多事物凑在一起。),那么字面上来看I/O multiplexing 就是将多个I/O凑在一起。就像下面这张图的前半部分一样,中间的那条线就是我们的单个线程,它通过记录传入的每一个I/O流的状态来同时管理多个IO。
IO多路复用的实现
我们来分析一下上面这张图
- 当进程调用select,进程就会被阻塞
- 此时内核会监视所有select负责的的socket,当socket的数据准备好后,就立即返回。
- 进程再调用read操作,数据就会从内核拷贝到进程。
其实多路复用的实现有多种方式:select、poll、epoll
selectors模块_client
1 | # -*- coding: utf-8 -*- |
selectors_serrer
1 | # -*- coding: utf-8 -*- |
聊天
client
1 | # -*- coding: utf-8 -*- |
server
1 | # -*- coding: utf-8 -*- |
非阻塞IO
client
1 | # -*- coding: utf-8 -*- |
server
1 | # -*- coding: utf-8 -*- |
IO多路复用
client
1 | # -*- coding: utf-8 -*- |
server
1 | # -*- coding: utf-8 -*- |
二、select_FTP
client
1 | # -*- coding: utf-8 -*- |
server
1 | # -*- coding: utf-8 -*- |
三、GIL
- GIL(全局解释器锁)(Global Interpreter Lock)是计算机程序设计语言解释器用于同步线程的工具,使得任何时刻一个进程仅有一个线程占用cpu
- 这就造成了多线程不能同时执行,并且增加了切换的开销,串行的效率可能更高
四、进程
- 进程定义:最小的资源单位
- 进程就是一个程序在一个数据集上的一次动态执行过程。(抽象)
- 进程一般由程序、数据集、进程控制块三部分组成。
- 我们编写的程序用来描述进程要完成哪些功能以及如何完成;
- 数据集则是程序在执行过程中所需要使用的资源;
- 进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系
- 统感知进程存在的唯一标志
1. 进程的调用
1 | # -*- coding: utf-8 -*- |
2. process类
1 | # -*- coding: utf-8 -*- |
3. 进程通信
1 | # -*- coding: utf-8 -*- |
4. 进程同步
1 | # -*- coding: utf-8 -*- |
5. 多进程
1 | # -*- coding: utf-8 -*- |
五、线程
1 | 线程:最小的执行单位 |
(1)、一个程序至少有一个进程,一个进程至少有一个线程.(进程可以理解成线程的容器)
(2)、进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
(3)、线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和
程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
(4)、进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调
度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程
自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈)但是
它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
1 | 同步锁(互斥锁):对某一段程序设置同步锁,在这段程序内禁止cpu切换,只能串行。 |
1. 线程继承
1 | # -*- coding: utf-8 -*- |
2. 计算密集型任务
1 | # -*- coding: utf-8 -*- |
3. 同步锁
1 | # -*- coding: utf-8 -*- |
4. 递归锁
1 | # -*- coding: utf-8 -*- |
5. 同步对象
1 | # -*- coding: utf-8 -*- |
6. 信号量
1 | # -*- coding: utf-8 -*- |
7. 队列
1 | """ |
8. 多线程一
1 | # -*- coding: utf-8 -*- |
9. 多线程二
1 | # -*- coding: utf-8 -*- |
10. 多线程三
1 | # -*- coding: utf-8 -*- |
11. 生产者消费者模型
1 | # -*- coding: utf-8 -*- |
六、协程
线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。
协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。
协程的适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;
greenlet
1 | # -*- coding: utf-8 -*- |
gevent
1 | # -*- coding: utf-8 -*- |
yield
1 | # -*- coding: utf-8 -*- |