Python笔记_第四篇_高阶编程_进程、线程、协程_1.进程
1. 多任务原理:
现代操作系统,像win,max os x,linux,unix等都支持多任务。
* 什么叫做多任务?
操作系统可以同时运行多个任务。
* 单核CPU实现多任务原理?
操作系统轮流让各个任务交替执行,比如QQ执行2us,切换到微信,再执行2us,在切换到其他应用,再执行2us... ...,如此交替往复。表面上看每个任务反复执行下去,但是CPU调度执行速度太快了,导致我们感觉就像所有任务都同时执行一样。
* 多核CPU实现多任务原理?
真正的并行执行多任务只能在多核CPU上实现,但是由于任务数量远远多于CPU核心数量,所以操作系统会把很多任务轮流调度到每个核心上执行。
* 并发和并行的概念:
并发:看上去是一起执行,任务多于CPU核心数。
并行:真正一起执行,任务数小于CPU核心数。
* 实现多任务的方式:
* 多进程模式
* 多线程模式
* 协程模式
* 多进程 + 多线程模式。
这里讲解前三种,另外,这部分内容还会提及到GPU的多任务原理(使用GPU强大的浮点运算功能,实现算法的快速运算)
2. 进程:
进程:对于操作系统而言,一个任务就是一个进程。进程是系统中程序执行和资源分配的基本单位。每个进程都有自己的数据段、代码段、堆栈段。
2.1 从一个单任务现象说起:
如下代码:
from time import sleep def run():
while True:
print("Thomas is a nice man")
sleep(1.2) if __name__ == '__main__':
while True:
print("Thomas is a good man")
sleep() run() #不会执行到run方法,只有上面的while循环结束才可以执行
# Thomas is a good man
# Thomas is a good man
# Thomas is a good man
# Thomas is a good man
我们发现代码只会执行good man,因为只有上面的循环结束才可以执行。其实在最初的代码编程中,就是一种这样的顺序执行方式。
2.2 启动进行实现多任务:multirprocessing库
我们通过进程库,创建一个进程,把想要执行的代码“丢入”进程当中去执行。
先看代码:
r"""
multiprocessing 库:
跨平台版本的多进行实现的模块。提供了Process类来代表一个进程对象。 """
from multiprocessing import Process
from time import sleep
import os def run(str):
while True:
# os.getpid()获得当前进程的id号码
# os.getppdi()获得当前进行的父进程id号码
print("Jerry is a %s man: 子进程%s--父进程%s" %(str,os.getpid(),os.getppid()))
sleep(1.2) if __name__ == '__main__':
print("主(父)进程启动!--%s" %(os.getpid()))
# 创建一个子进程:
# target说明进程执行的任务
p = Process(target=run,args=("nice",)) # 元组如果只有一个,后面要逗号
# 启动进程
p.start() while True:
print("Thomas is a good man")
sleep() # 不创建的进程都是主进程,首先执行的。
# 主(父)进程启动!--
# Thomas is a good man
# Jerry is a nice man: 子进程3280--父进程4368
# Thomas is a good man
说明1:我们发现主进程是一个默认进程,创不创建(不用创建)都会有一个父进程的存在。
说明2:os.getpid()方法是获得当前的进程id号码,process id。
说明3:p.start()表示的是启动子进程。
说明4:在创建进程的时候,参数是一个元组的形式,如果只有一个,后面要用逗号进行分割。
说明5:我们发现,子进程的运行过程,父进程不受子进程的影响。如果我们想在整个程序的运行过程中,父进程开启,等到子进程完全结束后,再结束父进程。如下:2.3 父进程的先后顺序。
2.3 父进程的先后顺序:
先看代码:
from multiprocessing import Process
from time import sleep def run():
while True:
print("启动子进程")
sleep()
print("子进程结束") if __name__ == '__main__':
print("主(父)进程启动!") p = Process(target=run) # 元组如果只有一个,后面要逗号
p.start() # 父进程的结束不影响子进程
# 如果我们让父进程等待子进程结束在执行父进程结束。
p.join() print("父进程结束!")
主(父)进程启动!
启动子进程
子进程结束
启动子进程
子进程结束
说明1:我们发现,我们通过p.join()的方法让父进程挡在子进程的门外,只有当子进程结束了,父进程再能结束(我们让子进程一直运行,这样父进程就一直结束不了了。),但是比如说我们有一个全局变量,这个全局变量在进程中是如何变化的?
2.4 全局变量在多个进程中不能共享:
看代码:
from multiprocessing import Process # 如果我们有一个全局变量
num = def run():
print("子进程开始")
global num
num +=
print(num)
print("子进程结束") if __name__ == '__main__':
print("父进程开始")
p = Process(target=run) # 加入括号编程函数的执行了。
p.start()
p.join() # 在兄弟进程中全局变量也是不会相互影响的
# p2 = Process(target=run) # 加入括号编程函数的执行了。
# p2.start()
# p2.join() # 在子进程中修改全局变量对父进程中的全局变量没有影响。
# 在创建子进程时对全局变量做了一个备份,父进程与子进程中的num是完全不同的两个变量。
print("父进程结束--%d" % num) 父进程开始
子进程开始 子进程结束
父进程结束--
说明1:在子进程中修改了全局变量对父进程中的全局变量没有影响。
说明2:在创建子进程时对全局变量做了一个备份,父进程与子进程中的num是两个完全不同的变量了。
说明3:现在我们是通过进程的方法启动,阻塞进行进程的创建。其实在实际的运行过程中,我们想CPU的多进程一起运行,还可以通过进程池的方式。
2.5 启动大量子进程(进程池Pool):
进程池,好比创建一个池子,把进程丢入到池子中,让电脑自动去分配进程,不用自己单个去创建。
看代码:
from multiprocessing import Pool
import time,os,random def run(name):
print("子进程%d启动,PID=%s" %(name,os.getpid()))
start = time.time()
time.sleep(random.choice([,,]))
end = time.time()
print("子进程%d结束,PID=%s, 耗时%.2f" % (name, os.getpid(),end-start)) if __name__ == '__main__':
print("主进程启动") # 创建多个进程
# 进程池
# 表示可以同时执行的进程数量
# Pool默认是大小CPU核心数
pp = Pool() # 创建进程放入进程池,统一管理
for i in range():
pp.apply_async(run,args=(i,)) # 在调用join之前必须先调用close,调用close之后不能再继续添加新的进程了。
pp.close()
# 进程池对象调用的join,会等待进程池中所有的子进程结束完毕,再去执行父进程。
pp.join() print("主进程结束") # 主进程启动
# 子进程0启动,PID=
# 子进程1启动,PID=
# 子进程0结束,PID=, 耗时2.
# 子进程2启动,PID=
# 子进程1结束,PID=, 耗时2.
# 子进程3启动,PID=
# 子进程2结束,PID=, 耗时2.
# 子进程4启动,PID=
# 子进程3结束,PID=, 耗时2.
# 子进程4结束,PID=, 耗时2.
# 主进程结束
说明1:创建进程池使用的Pool模块。
说明2:把程序丢入进程池,我们用的是pp.apply_async这个方法。
说明3:调用join之前必须先调用close,调用close之后不能再继续添加新的进程了。
说明4:进程池对象调用join,会等待进程池中所有的子进程技术完毕,再去执行父进程。
2.6 举例:通过多进程来实现文件的拷贝:
代码如下:
from multiprocessing import Pool
import time,os def copyFile(path,toPath):
fr = open(path,"r")
fw = open(toPath,"w") context = fr.read()
fr.write(context)
fr.close()
fw.close() path = r""
toPath = r""
# 读取path下的所有文件
filesList = os.listdir(path) # 启动for循环处理每个文件
starttime = time.time()
pp = Pool()
for fileName in filesList:
pp.apply_async(copyFile,args=(os.path.join(path,fileName),os.path.join(toPath,fileName)))
endtime = time.time()
print("总耗时%.4f" %(endtime-starttime))
2.7 进程间的通信(Queue方法/队列方法):
先看代码:
from multiprocessing import Process,Queue
import os,time def write(q):
print("启动写write进程%s" % os.getpid())
for chr in ["A","B","C","D"]:
q.put(chr)
time.sleep()
print("结束写write进程%s" % os.getpid()) def read(q):
print("启动读read进程%s" % os.getpid())
while True:
value = q.get(True)
print("value=" + value) print("结束读read进程%s" % os.getpid()) if __name__ == '__main__':
# 父进程创建队列,并传递给子进程
q = Queue()
pw = Process(target=write,args=(q,))
pr = Process(target=read,args=(q,)) pw.start()
pr.start() #
pw.join()
# pr进程是一个死循环,无法等待其结束,只能强行结束
pr.terminate() print("父进程结束") while True:
pass 启动写write进程7296
启动读read进程864
value=A
value=B
value=C
value=D
结束写write进程7296
父进程结束
说明1:我们在main函数中创建了一个进程的队列(队列一共有4中,这里使用的是进程的队列),通过两个读写进程的相互交互,实现了读写的方式。
说明2:如果一个进程是一个四选好,无法等待其结果结束,使用.pr.terminate()的方法进行强行的关闭。
Python笔记_第四篇_高阶编程_进程、线程、协程_1.进程的更多相关文章
- Python 进程线程协程 GIL 闭包 与高阶函数(五)
Python 进程线程协程 GIL 闭包 与高阶函数(五) 1 GIL线程全局锁 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的 ...
- python自动化开发学习 进程, 线程, 协程
python自动化开发学习 进程, 线程, 协程 前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...
- 多道技术 进程 线程 协程 GIL锁 同步异步 高并发的解决方案 生产者消费者模型
本文基本内容 多道技术 进程 线程 协程 并发 多线程 多进程 线程池 进程池 GIL锁 互斥锁 网络IO 同步 异步等 实现高并发的几种方式 协程:单线程实现并发 一 多道技术 产生背景 所有程序串 ...
- Python并发编程系列之常用概念剖析:并行 串行 并发 同步 异步 阻塞 非阻塞 进程 线程 协程
1 引言 并发.并行.串行.同步.异步.阻塞.非阻塞.进程.线程.协程是并发编程中的常见概念,相似却也有却不尽相同,令人头痛,这一篇博文中我们来区分一下这些概念. 2 并发与并行 在解释并发与并行之前 ...
- python的进程/线程/协程
1.python的多线程 多线程就是在同一时刻执行多个不同的程序,然而python中的多线程并不能真正的实现并行,这是由于cpython解释器中的GIL(全局解释器锁)捣的鬼,这把锁保证了同一时刻只有 ...
- python基础(16)-进程&线程&协程
进程之multiprocessing模块 Process(进程) Process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建. 介绍 初始化参数 Process([group [, t ...
- Python笔记_第四篇_高阶编程_进程、线程、协程_5.GPU加速
Numba:高性能计算的高生产率 在这篇文章中,笔者将向你介绍一个来自Anaconda的Python编译器Numba,它可以在CUDA-capable GPU或多核cpu上编译Python代码.Pyt ...
- Python笔记_第四篇_高阶编程_进程、线程、协程_4.协程
1.协程的概念: 子程序或者子函数,在所有语言中都是层级调用,比如A调用B,再B执行的过程中又可以调用C,C执行完毕返回,B执行返回,最后是A执行完毕返回.是通过栈来实现的,一个线程就是执行一个自称, ...
- Python笔记_第四篇_高阶编程_进程、线程、协程_3.进程vs线程
1.多任务的实现原理: 通常我们会设计Mater-Workder模式,Master负责分配任务,Worker负责执行任务,因此多任务环境下,通常是一个Master,多个Worker 2.多进程: 主进 ...
随机推荐
- LINUX——LVM逻辑卷管理
LVM: logical volumes manager LVM逻辑卷部署 物理卷—>卷组—>逻辑卷 第一步:关机添加磁盘:两个磁盘可以构成一个磁盘组. 第二步:查看磁盘 # ls /de ...
- 虚拟化安全服务器のIP修改配置
1)进入网卡配置文件目录(以centos7.6为例) cd /etc/sysconfig/network-scripts 2)编辑配置文件(根据自己机器实际网卡进行编辑), 如Vi ifcfg ...
- NAT的三种方式
NAT的三种方式: 一.端口NAT acces-list 1 permit IP/Mask ip nat inside source list “number” interface fastether ...
- 六十五、SAP中通过BREAK-POINT下断点,进行调试
一.代码如下,有2个断点的按钮,可以可以写入BREAK-POINT人工断点 二.运行之后,程序会被断下来, 四个执行按钮,意思分别为:单步进入子程序,单步不进入子程序,返回外面,执行到断点处 三.我们 ...
- HDU 4866 多校1 主席树+扫描线
终于是解决了这个题目了 不过不知道下一次碰到主席树到底做不做的出来,这个东西稍微难一点就不一定能做得出 离散化+扫描线式的建树,所以对于某个坐标二分找到对应的那颗主席树,即搜索出结果即可(因为是扫描线 ...
- 吴裕雄--天生自然C++语言学习笔记:C++ STL 教程
C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表.队列.栈. C++ 标准模板库的核心包括以 ...
- word 2007 文档中添加文件
1. "插入"->"对象",出现的下拉框中选择"对象" 2.弹出界面 3.切换至"由文件创建",点击"浏 ...
- python 对axis的理解
首先请看一下官方帮助的解释: 轴用来为超过一维的数组定义的属性,二维数据拥有两个轴:第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸. 注意看,官方对于0和1的解释是轴,也就是坐标轴.而坐标轴是有 ...
- s5pc100开发板linux内核移植
相关软件下载地址:http://pan.baidu.com/s/16yo8Y 应用于FSC100开发板 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc linux-2.6 ...
- slf4j NoSuchMethodError 错误 ---- 版本冲突
java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/Stri ...