多任务编程-进程-线程
多任务编程
一: 进程
二: 多进程
三: 线程
四: 多线程
五: 其他问题
意义 : 充分利用计算机的资源提高程序的运行效率
定义 : 通过应用程序利用计算机的多个核心达到同时执行多个任务的目的,一次提高计算机运行效率。
实施方案 : 多进程 多线程
并行 : 多个计算机核心在同时处理多个任务,这时多个任务间是并行关系。
并发 : 同时处理多个任务,内核在多个任务间不断的切换,达到好像都在处理运行的效果。但实际一个时间点内核只能处理其中一个任务。
进程
定义 : 程序在计算机中的一次运行过程
程序 : 是一个可执行的文件,是静态的占有磁盘空间,不占有计算机的运行资源
进程 : 进程是一个动态过程的描述,占有计算机的资源,有一定的生命周期
* 同一个程序的不同运行过程是不同的进程,占用资源和生命周期都不一样。
进程的创建流程
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. 每个进程空间独立,各自占有一定的虚拟内存
------------------------------------------------------------------------------
多任务编程
import os
pid = os.fork() (注意:在Windows上没有该模块)
功能 : 创建新的进程
参数 : 无
返回值: 失败返回一个负数
成功 : 在原有进程中返回新的进程的PID号
在新的进程中返回0
# -*- coding: utf-8 -*- import os from time import sleep print("*******************") a = 1 pid = os.fork() if pid < 0: print("创建进程失败") elif pid == 0: print("这是新的进程") print("a = ", a) a = 10000 else: sleep(1) print("这是原有进程") print("parent a =", a) print("演示完毕")
* 子进程会复制父进程全部代码段,包括fork之前产生的内存空间
* 子进程从fork的下一句开始执行,与父进程互不干扰
* 父子进程的执行顺序是不一定的,父子进程公用一个终端显示
* 父子进程通常会根据fork返回值得差异选择执行不同的代码。所以if结构几乎是fork的固定搭配
* 父子进程空间独立,操作的都是本空间的内容,互不影响
* 子进程也有自己的特性,比如PID号,PCB,命令集等
进程相关函数
#获取进程PID
os.getpid()
功能 : 获取当前进程的进程号
返回值 : 返回进程号
os.getppid()
功能 : 获取当前进程父进程的PID号
返回值 : 返回进程号
进程退出
os._exit(status)
功能 : 进程退出
参数 : 进程的退出状态
sys.exit([status])
功能 : 进程退出
参数 : 数字表示退出状态,不写默认为0
字符串,表示退出时打印的内容
* sys.exit 可以通过捕获 SystemExit异常阻止退出
import os from time import sleep pid = os.fork() if pid < 0: print("Create process failed") elif pid == 0: sleep(1) #获取当前进程的PID print("Child get pid:",os.getpid()) #获取父进程的PID print("Child get parent pid:",os.getppid()) else: print("parent get child pid:",pid) print("parent get pid:",os.getpid())
孤儿进程: 父进程先于子进程退出,此时子进程就称为孤儿进程。 * 孤儿进程会被操作系统指定的进程收养,系统进程就成为孤儿进程的新的父进程 僵尸进程: 子进程先于父进程退出,但是父进程没有处理子进程的退出状态,此时子进程就会成为僵尸进程。 * 僵尸进程会存留少量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() 注意:在windows中Process()必须放到# if __name__ == '__main__':下
由于Windows没有fork,多处理模块启动一个新的Python进程并导入调用模块。
如果在导入时调用Process(),那么这将启动无限继承的新进程(或直到机器耗尽资源)。
这是隐藏对Process()内部调用的原,使用if __name__ == “__main __”,这个if语句中的语句将不会在导入时被调用。
功能 : 创建进程对象
参数 : name 进程名称 Process-1
target 绑定函数
args 元组 给target函数按照位置传参
kwargs 字典 给target函数按照键值对传参
p.start()
功能:启动进程
* target函数会自动执行,此时进程真正被创建
p.join([timeout])
功能 : 阻塞等待回收子进程
参数 : 超时时间
* 使用multiprocessing创建子进程,同样子进程复制父进程的全部代码段,父子进程各自执行互不影响,父子进程有各自的运行空间
* 如果不使用join回收子进程则子进程退出后会成为僵尸进程
* 使用multiprocessing创建子进程往往父进程只是用来创建进程回收进程
# -*- coding: utf-8 -*-
from multiprocessing import Process
from time import sleep
def p1():
print('Hello!')
if __name__ == '__main__':
p = Process(target=p1)
p.start()
sleep(2)
print('这是父进程!')
p.join()
注意
1. 如果子进程从父进程拷贝对象,对象和网络或者文件相关联,那么父子进程会使用同一套对象属性,相互有一定的关联性
2. 如果在子进程中单独创建对象,则和父进程完全没有关联
Process进程对象属性
p.start()
p.join()
p.is_alive()
判断进程生命周期状态,处于生命周期得到True否则返回False
p.name 进程名称 默认为Process-1
p.pid 进程的PID号
p.daemon
默认状态False 主进程退出不会影响子进程执行
如果设置为True 则子进程会随着主进程结束而结束
* 要在start前设置
* 一般不和join一起使用
创建自定义进程类
1. 继承Process
2. 编写自己的__init__ ,同时加载父类init方法
3. 重写run方法,可以通过生成的对象调用start自动运行
多进程
线程
浙公网安备 33010602011771号