文章目录

  • 进程 (Process)
    • 多进程编程
      • multiprocessing 模块创建进程
      • 创建自定义进程类
      • 进程池技术
    • 进程间通信 (IPC)
      • 管道通信 Pipe
      • 消息队列
      • 共享内存
    • 信号通信
      • 信号量(信号灯)
  • 线程
      • 线程同步互斥方法
    • 多线程并发

意义 : 充分利用计算机的资源提高程序的运行效率

定义 : 通过应用程序利用计算机的多个核心达到同时执行多个任务的目的,一次提高计算机运行效率。

实施方案 : 多进程 多线程

并行 : 多个计算机核心在同时处理多个任务,这时多个任务间是并行关系。

并发 : 同时处理多个任务,内核在多个任务间不断的切换,达到好像都在处理运行的效果。但实际一个时间点内核只能处理其中一个任务。

进程 (Process)

定义 : 程序在计算机中的一次运行过程

程序 : 是一个可执行的文件,是静态的占有磁盘空间,不占有计算机的运行资源

进程 : 进程是一个动态过程的描述,占有计算机的资源,有一定的生命周期

  • 同一个程序的不同运行过程是不同的进程,占用资源和生命周期都不一样。

进程的创建流程
1.用户空间通过运行程序或者调用接口发起创建进程
2.操作系统接受用户请求,开始创建进程
3.操作系统分配计算机资源,确定进程状态,开辟进程空间等工作
4.操作系统将创建好的进程提供给应用程序使用

cpu时间片

如果一个进程占有计算机核心,我们称为改进程占有计算机cpu时间片。

  • 多个任务之间是争夺cpu的关系
  • 谁占有cpu最终是操作系统决定

PCB (进程控制块)
在内存中开辟的一块空间,用来记录进程的信息

  • 进程控制块是操作系统查找识别进程的标志

进程信息 : ps -aux

PID(process ID) : 在操作系统中每个进程都有一个唯一的ID号用来区别于其他进程。ID号由操作系统自动分配,是一个大于0的整数

父子进程 : 在系统中除了初始化进程,每一个进程都有一个父进程,可能有0个或者多个子进程。由此形成父子进程关系。

查看进程树 : pstree
查看父进程PID: ps -ajx

进程的状态

三态
* 就绪态 : 进程具备执行条件,等待系统分配资源
* 运行态 : 进程占有cpu处于运行状态
* 等待态 : 进程暂时不具备执行条件,阻塞等待满 足条件后再执行

五态 (三态基础上增加新建态,终止态)
* 新建态 : 创建一个新的进程,获取资源的过程
* 终止态 : 进程执行结束,资源释放回收的过程

ps -aux —> STAT

S 等待态 (可中断等待)
D 等待态 (不可中断等待)
T 等待态 (暂停状态)
R 运行态 (包含就绪态)
Z 僵尸进程

< 高优先级进程
N 优先级较低
l 有子进程的
s 会话组组长

  • 前台进程

进程优先级

作用 : 决定了一个进程的执行权限和占有资源的优先程度

查看进程优先级
top 动态查看系统中的进程信息, 用<>翻页
取值范围 -20 – 19 -20优先级最高

使用指定的优先级运行程序
nice : 指定运行的优先级

e.g.   nice -9  ./while.py   以优先级9运行nice --9  ./while.py  以-9优先级运行

进程特征

  1. 进程之间运行互不影响 各自独立运行
  2. 进程是操作系统资源分配的最小单位
  3. 每个进程空间独立,各自占有一定的虚拟内存

要求 :

  1. 什么是进程,进程和程序的区别
  2. 了解进程特征
  3. 清楚进程每种状态,以及状态之间的转换关系

多进程编程

import  os  pid = os.fork()
功能 : 创建新的进程
参数 : 无
返回值: 失败返回一个负数
成功 : 在原有进程中返回新的进程的PID号,在新的进程中返回0
  • 子进程会复制父进程全部代码段,包括fork之前产生的内存空间
  • 子进程从fork的下一句开始执行,与父进程互不干扰
  • 父子进程的执行顺序是不一定的,父子进程公用一个终端显示
  • 父子进程通常会根据fork返回值得差异选择执行不同的代码。所以if结构几乎是fork的固定搭配
  • 父子进程空间独立,操作的都是本空间的内容,互不影响
  • 子进程也有自己的特性,比如PID号,PCB,命令集等

进程相关函数

获取进程PID
os.getpid()
功能 : 获取当前进程的进程号
返回值 : 返回进程号

os.getppid()
功能 : 获取当前进程父进程的PID号
返回值 : 返回进程号

进程退出

os._exit(status)
功能 : 进程退出
参数 : 进程的退出状态

sys.exit([status])
功能 : 进程退出
参数 : 数字表示退出状态,不写默认为0
字符串,表示退出时打印的内容

  • sys.exit 可以通过捕获 SystemExit异常阻止退出

孤儿进程: 父进程先于子进程退出,此时子进程就称为孤儿进程。

  • 孤儿进程会被操作系统指定的进程收养,系统进程就成为孤儿进程的新的父进程

僵尸进程: 子进程先于父进程退出,但是父进程没有处理子进程的退出状态,此时子进程就会成为僵尸进程。

  • 僵尸进程会存留少量PCB信息在内存中,大量的僵尸进程会消耗系统资源,应该避免僵尸进程产生

如何避免僵尸进程产生
* 处理子进程退出状态
pid,status = os.wait()
功能 :在父进程中阻塞等待处理子进程退出
返回值: pid 退出的子进程的PID号
status 获取子进程退出状态

pid,status = os.waitpid(pid,option)
功能 :在父进程中阻塞等待处理子进程退出
参数 : pid  -1 表示等待任意子进程退出>0 表示等待对应PID号的子进程退出option  0 表示阻塞等待WNOHANG 表示非阻塞返回值: pid 退出的子进程的PID号status  获取子进程退出状态waitpid(-1,0)  ===> wait()* 让父进程先退出1. 父进程创建子进程等待子进程退出2. 子进程创建二级子进程后立即退出3. 二级子进程称为孤儿,和原来的父进程各自执行事件

multiprocessing 模块创建进程

  1. 需要将要执行的事情封装为函数
  2. 使用multiprocessing模块中Process类创建进程对象
  3. 通过对象属性设置和Process的初始化函数对进程进行设置,绑定要执行的函数
  4. 启动进程,会自动执行进程绑定的函数
  5. 完成进程的回收
Process()
功能 : 创建进程对象
参数 : name  进程名称  Process-1target  绑定函数 args  元组  给target函数按照位置传参kwargs  字典  给target函数按照键值对传参p.start()
功能:启动进程
* target函数会自动执行,此时进程真正被创建p.join([timeout])
功能 : 阻塞等待回收子进程
参数 : 超时时间* 使用multiprocessing创建子进程,同样子进程复制父进程的全部代码段,
* 父子进程各自执行互不影响,父子进程有各自的运行空间* 如果不使用join回收子进程则子进程退出后会成为僵尸进程
* 使用multiprocessing创建子进程往往父进程只是用来创建进程回收进程Process进程对象属性p.start()
p.join()p.is_alive()
判断进程生命周期状态,处于生命周期得到True否则返回Falsep.name 进程名称 默认为Process-1
p.pid  进程的PID号p.daemon
默认状态False  主进程退出不会影响子进程执行
如果设置为True 则子进程会随着主进程结束而结束* 要在start前设置
* 一般不和join一起使用

创建自定义进程类

  1. 继承Process
  2. 编写自己的__init__ ,同时加载父类init方法
  3. 重写run方法,可以通过生成的对象调用start自动运行

优点 : 可以使用计算机多核,进行任务的并发执行,提高执行效率空间独立,数据安全 运行不受其他进程影响,创建方便
缺点 : 进程的创建和删除消耗的系统资源较多

进程池技术

产生原因 : 如果有大量任务需要多进程完成,则可能需要频繁的创建删除进程,给进算计带来较多的资源消耗。

原理 : 创建适当的进程放入进程池,用来处理待处理事件,处理完毕后进程不销毁,仍然在进程池中等待处理其他事件。 进程的复用降低了资源的消耗

使用方法

  1. 创建进程池,在池内放入适当的进程
  2. 将事件加入到进程池等待队列
  3. 不断取进程执行事件,直到所有事件执行完毕
  4. 关闭进程池,回收进程
from multipeocessing import  PoolPool(processes)
功能 : 创建进程池对象
参数 :表示进程池中有多少进程pool.apply_async(func,args,kwds)
功能 : 将事件放入到进程池队列
参数 : func 事件函数args 以元组形式给func传参kwds 以字典形式给func传参
返回值 : 返回一个代表进程池事件的对象pool.apply(func,args,kwds)
功能 : 将事件放入到进程池队列
参数 : func 事件函数args 以元组形式给func传参kwds 以字典形式给func传参pool.close()
功能: 关闭进程池pool.join()
功能:回收进程池pool.map(func,iter)
功能: 将要做的时间放入进程池
参数: func  要执行的函数iter  迭代对象
返回值 : 返回事件函数的返回值列表

进程间通信 (IPC)

原因 : 进程空间相对独立,资源无法相互获取,此时在不同进程间通信需要专门方法。

进程间通信方法 : 管道 消息队列 共享内存 信号
信号量 套接字

管道通信 Pipe

通信原理 : 在内存中开辟管道空间,生成管道操作对象,多个进程使用"同一个"管道对象进行操作即可实现通信

multiprocessing ---》 Pipefd1,fd2 = Pipe(duplex = True)
功能 : 创建管道
参数 : 默认表示双向管道如果设置为False则为单向管道
返回值 : 表示管道的两端如果是双向管道 都可以读写如果是单向管道 则fd1只读 fd2只写fd.recv()
功能 : 从管道读取信息
返回值: 读取到的内容* 如果管道为空则阻塞fd.send(data)
功能:向管道写入内容
参数: 要写入的内容
* 可以发送python数据类型

消息队列

队列 : 先进先出
通信原理 : 在内存中建立队列数据结构模型。多个进程都可以通过队列存入内容,取出内容的顺序和存入顺序保持一致

创建队列
q = Queue(maxsize = 0)
功能 : 创建消息队列
参数 : 表示最多存放多少消息。默认表示根据内存分配存          储
返回值 : 队列对象q.put(data,[block,timeout])
功能: 向队列存储消息
参数 :data 要存的内容block 默认队列满时会阻塞,设置为False则非阻塞timeout 超时时间data = q.get([block,timeout])
功能:获取队列消息
参数:block 默认队列空时会阻塞,设置为False则非阻塞timeout 超时时间
返回值 : 返回取出的内容q.full()   判断队列是否为满
q.empty()  判断队列是否为空
q.qsize()  判断队列中消息数量
q.close()  关闭队列

共享内存

通信原理:在内存空开辟一块空间,对多个进程可见,进程可以写入输入,但是每次写入的内容会覆盖之前的内容。

obj = Value(ctype,obj)
功能 : 开辟共享内存空间
参数 : ctype  要存储的数据类型obj  共享内存的初始化数据
返回 :共享内存对象obj.value 即为共享内存值,对其修改即修改共享内存obj = Array(ctype,obj)
功能 : 开辟共享内存空间
参数 : ctype  要存储的数据格式obj  初始化存入的内容 比如列表,字符串如果是整数则表示开辟空间的个数
返回值 : 返回共享内存对象* 可以通过遍历过户每个元素的值e.g.  [1,2,3]  ---> obj[1] == 2* 如果存入的是字符串obj.value 表示字符串的首地址
           管道         消息队列       共享内存
开辟空间   内存         内存           内存读写方式   两端读写     先进先出       覆盖之前内容双向/单向效率       一般          一般          较高应用       多用于父     广泛灵活       需要注意子进程                      进行互斥操作

信号通信

一个进程向另一个进程发送一个信号来传递某种讯息,接受者根据接收到的信号进行相应的行为

kill -l 查看系统信号
kill -sig PID 向一个进程发送信号

关于信号
信号名称 信号含义 默认处理方法

SIGHUP 连接断开
SIGINT CTRU-C
SIGQUIT CTRU-
SIGTSTP CTRL-Z
SIGKILL 终止一个进程
SIGSTOP 暂停一个进程
SIGALRM 时钟信号
SIGCHLD 子进程状态改变时给父进程发出

python 发送信号signal  os.kill(pid,sig)
功能: 发送信号
参数: pid 目标进程sig 要发送的信号
import signalsignal.alarm(sec)
功能 : 向自身发送时钟信号 --》 SIGALRM
参数 : sec  时钟时间* 进程中只能有一个时钟,第二个会覆盖第一个时间同步执行 : 按照顺序逐句执行,一步完成再做下一步
异步执行 : 在执行过程中利用内核记录延迟发生或者准备             处理的事件。这样不影响应用层的持续执行。             当事件发生时再由内核告知应用层处理* 信号是唯一的异步通信方法signal.pause()
功能:阻塞等待接收一个信号signal.signal(signum,handler)
功能: 处理信号
参数: signum  要处理的信号handler 信号的处理方法 SIG_DFL  表示使用默认的方法处理SIG_IGN  表示忽略这个信号func     传入一个函数表示用指定函数处理def func(sig,frame)sig: 捕获到的信号frame : 信号对象

信号量(信号灯)

原理 : 给定一个数量,对多个进程可见,且多个进程都可以操作。进程通过对数量多少的判断执行各自的行为。

multiprocessing --》 Semaphore()sem = Semaphore(num)
功能: 创建信号量
参数: 信号量初始值
返回: 信号量对象sem.get_value()  获取信号量值
sem.acquire() 将信号量减1  当信号量为0会阻塞
sem.release() 将信号量加1进程的同步互斥临界资源 :多个进程或者线程都能够操作的共享资源
临界区 : 操作临界资源的代码段同步 : 同步是一种合作关系,为完成某个任务,多进程或者多线程之间形成一种协调,按照约定或条件执行操作临界资源。互斥 : 互斥是一种制约关系,当一个进程或者线程使用临界资源时进行上锁处理,当另一个进程使用时会阻塞等待,直到解锁后才能继续使用。Event  事件multiprocessing  --》 Event创建事件对象
e = Event()设置事件阻塞
e.wait([timeout])事件设置 当事件被设置后e.wait()不再阻塞
e.set()清除设置 当事件设置被clear后 e.wait又会阻塞
e.clear()事件状态判断
e.is_set()Lock 锁创建对象
lock = Lock() lock.acquire() 上锁  如果锁已经是上锁状态调用此函数会阻塞lock.release() 解锁with lock:   上锁........解锁

线程

线程也是一种多任务编程方法,可以利用计算机多核资源完成程序的并发执行。线程又被称为轻量级的进程。

线程特征

  • 线程计算机多核分配的最小单位
  • 一个进程可以包含多个线程
  • 线程也是一个运行的过程,消耗计算机资源,多个线程共享进程的资源和空间
  • 线程的创建删除消耗的资源都要远远小于进程
  • 多个线程之间执行互不干扰
  • 线程也有自己的特有属性,比如指令集 ID
threading 模块创建线程threading.Thread()
功能 : 创建线程对象
参数 :name  线程名称  默认 Thread-1 target  线程函数 args  元组   给线程函数位置传参kwargs  字典  给线程函数键值传参t.start()  启动线程 自动运行线程函数
t.join([timeout])  回收线程线程对象属性t.is_alive()  查看线程状态
t.name  线程名称
t.setName()  设置线程名称
t.getName()  获取线程名称
threading.currentThread()  获取当前线程对象t.daemon 属性
默认情况主线程退出不会影响分支线程执行
如果设置为True 则分支线程随主线程退出设置方法:
t.daenon = True
t.setDaemon(True)判断属性值
t.isDaemon()* 要在start前设置,不会和join同用创建自己的线程类
步骤:
1.继承Thread
2.加载Thread中的__init__
3.重写run方法

线程通信

通信方法: 多个线程共享进程的空间,所以线程间通            信使用全局变量完成。注意事项: 线程间使用全局变量往往要同步互斥机制            保证通信安全

线程同步互斥方法

线程的event
e = threading.Event()  创建事件对象
e.wait([timeout])  如果e为设置状态则不阻塞否则阻塞
e.set()  将e变为设置状态
e.clear()  清除设置线程锁
lock = threading.Lock()  创建锁对象
lock.acquire()  上锁
lock.release()  解锁* 也可以通过with上锁,上锁状态调用acquire会阻塞

多线程并发

threading 的多线程并发

对比多进程并发:
* 消耗资源较少
* 线程应该更注意共享资源的操作
* 在python中应该注意GIL问题,网络延迟较高,线程并 发也是一种可行的办法

实现步骤
1. 创建套接字,绑定监听
2. 接收客户端请求,创建新的线程
3. 主线程继续接收其他客户端连接
4. 分支线程启动对应的函数处理客户端请求
5. 当客户端断开,则分支线程结束

cookie

import tracebacktraceback.print_exc()
功能 : 更详细的打印异常信息集成模块的使用
python3 socketserver功能 : 通过模块的不同类的组合完成多进程/多线程 的           tcp/udp的并发StreamRequestHandler  处理tcp套接字请求
DatagramRequestHandler  处理udp套接字请求TCPServer  创建tcp server
UDPServer  创建udp serverForkingMixIn   创建多进程
ForkingTCPServer -->  ForkingMinIn + TCPServer
ForkingUDPServer -->  ForkingMinIn + UDPServerThreadingMixIn  创建多线程
ThreadingTCPServer --> ThreadingMinIn + TCPServer
ThreadingUDPServer --> ThreadingMinIn + UDPServer

HTTPServer V2.0

  1. 接收客户端请求
  2. 解析客户端请求
  3. 组织数据,形成HTTP response
  4. 将数据发送给客户端

升级

  1. 采用多线程并发接收多个客户端请求
  2. 基本的请求解析,根据请求返回相应的内容
  3. 除了可以请求静态网页,也可以请求简单的数据
  4. 将功能封装在一个类中

技术点 :

  1. socket tcp 套接字
  2. http协议的请求响应格式
  3. 线程并发的创建方法
  4. 类的基本使用

协程基础

定义 : 纤程,微线程。协程的本质是一个单线程程序,所以协程不能够使用计算机多核资源。

作用 : 能够高效的完成并发任务, 占用较少的资源。因 此协程的并发量较高

原理 : 通过记录应用层的上下文栈区,实现在运行中进行上下文跳转,达到可以选择性地运行想要运行的部分,以此提高程序的运行效率。

优点 : 消耗资源少
无需切换开销
无需同步互斥
IO并发性好

缺点 : 无法利用计算机多核

yield —》 协程实现的基本关键字

greenletgreenlet.greenlet()  生成协程对象
gr.switch() 选择要执行的协程事件gevent1. 将协程事件封装为函数
2. 生成协程对象gevent.spawn(func,argv)功能 : 生成协程对象参数 : func  协程函数argv  给协程函数传参返回值 : 返回协程对象3.回收协程gevent.joinall()功能 : 回收协程参数: 列表 将要回收的协程放入列表gevent.sleep(n)功能: 设置协程阻塞,让协程跳转参数: n  阻塞时间from gevent import monkey
monkey.patch_all()
功能: 修改套接字的IO阻塞行为* 必须在socket导入之前使用

python多任务编程相关推荐

  1. python多任务编程_python线程的多任务编程

    多任务 多任务介绍 对于人来说,一边听歌,一边跳舞就是多任务. 对于电脑,简单的说,同一时间执行多个程序处理数据叫做多任务 多任务理解 单核CPU 单核cpu在处理多任务的时候是根据时间片轮转的方式进 ...

  2. python高级编程-网络编程、多任务

    python高级编程 1 IP地址 用来在网络中标记一台电脑:在本地局域网上是唯一的. 2 端口 一个程序需要收发网络数据,就需要端口号. 3 socket 创建socket # 创建tcp sock ...

  3. Python网络编程(线程通信、GIL、服务器模型)

    什么是进程.进程的概念? 进程的概念主要有两点: 第一,进程是一个实体.每一个进程都有它自己的地址空间, 一般情况下,包括文本区域(text region).数据区域(data region)和堆栈( ...

  4. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)...

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程并行与并发同步与异步阻塞与非阻塞CPU密集型与IO密集型 线程与进程 进程 前言 ...

  5. Python并发编程理论篇

    Python并发编程理论篇 前言 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. 很多已经做案例的人,却不知道如何去学习更加高深的知识 ...

  6. python核心编程--笔记(不定时跟新)(转)

    的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找python路径 1.4 –v   ...

  7. python编程入门-Python 异步编程入门

    本文是写给 JavaScript 程序员的 Python 教程. Python 的异步编程,其他人可能觉得很难,但是 JavaScript 程序员应该特别容易理解,因为两者的概念和语法类似.JavaS ...

  8. python多进程编程_【玩树莓】编程篇(八)Python多线程、多进程编程

    1.多任务编程 除了计算性能和图形显示以外,树莓派区别于Arduino的一大特点就是运行多任务操作系统.通过多任务系统用户可以同时执行多个互相独立的程序(任务),来完成不同的操作. 利用Python的 ...

  9. Python -- 网络编程

    目录 1.网络通信的概念 2.IP地址 3.网络通信方式 3.1 直接通信 3.2 使用集线通信 3.3 通用交换机通信 3.4 使用路由器连接多个网络 3.5 复杂的通信过程 4.端口 4.1 端口 ...

最新文章

  1. 19.Remove Nth Node From End of List
  2. [ZCCAD-2006.12]CAD练习图例
  3. 变量的定义 声明和初始化和static
  4. 别把机器学习和人工智能搞混了!
  5. 华为安卓11是鸿蒙系统吗,恭喜华为手机,EMUI11曝光,是披着Android 11的“鸿蒙系统”?...
  6. 8、使用SELECTI...INTO OUTFILE导出表数据
  7. linux 进入一个中文乱码的目录的方法
  8. windows多用户 文件夹不共享_手把手教你如何使用Tekla多用户
  9. MySQL反斜杠 ‘\\‘ 插入数据库丢失
  10. 服务器安装、卸载宝塔面板
  11. 药品质量检测方法:电感耦合等离子体质谱仪
  12. android 指纹比对方法,指纹识别功能方面对比_手机Android频道-中关村在线
  13. 记录:nodejs 裁切图片的方法
  14. 微信小程序参数传递获取当前页面的url和参数
  15. hdu6194 string string string
  16. 一个初学者→全栈工程师的学习之路(1)——关于全栈工程师的理解
  17. 烧写android到开发板,烧写开发板_RZMars的技术博客_51CTO博客
  18. android webview问题汇总
  19. 2.2总线的性能指标
  20. HP惠普工作站无法启动虚拟机和蓝屏出现Technical information Stop:0x0000007B的解决办法

热门文章

  1. 简单的入门Android开发
  2. Linux Mint 安装 Docker Engine
  3. 万亿级重磅!刚刚,新一批基金投顾资格正式获批!广发、博时、招商等在列
  4. CPU性能测试——CoreMark篇
  5. 一次性就能学会的文件操作!(文件操作函数详解)
  6. 日常练习!加强网络部分!!
  7. 软件---网景战Microsoft
  8. 8749(07072402)流氓软件解决方案
  9. Lululemon的商业逻辑
  10. Facebook股价之“殇”