第三十天- 进程 Process模块 空间隔离
1.进程:
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。我们自己在python文件中写了一些代码,这叫做程序,运行这个python文件的时候,这叫做进程。
狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)
广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
举例:比如py1文件中有个变量a=1,py2文件中有个变量a=2,他们两个会冲突吗?不会的,因为两个文件运行起来后是两个进程,操作系统让他们在内存上隔离开。
2.并发、并行:
并发:是伪并行,即看起来是同时运行。单个cpu+多道技术就可以实现并发,(并行也属于并发)
并行:并行:同时运行,只有具备多个cpu才能实现并行
3.同步/异步 与 阻塞和非阻塞:
1.进程状态介绍:
(1)就绪(Ready)状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
(2)执行/运行(Running)状态当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。
(3)阻塞(Blocked)状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。
事件请求:input、sleep、文件输入输出、recv、accept
事件发生:sleep、input等完成了
时间片到了之后有回到就绪状态,这三个状态不断的在转换
2.同步/异步 与 阻塞和非阻塞:
(1)同步阻塞形式:效率最低。拿上面的例子来说,就是你专心排队,什么别的事都不做。
(2)异步阻塞形式:如果在排队取餐的人采用的是异步的方式去等待消息被触发(通知),也就是领了一张小纸条,假如在这段时间里他不能做其它的事情,就在那坐着等着,不能玩游戏等,那么很显然,这个人被阻塞在了这个等待的操作上面;
(3)同步非阻塞形式:实际上是效率低下,想象一下你一边打着电话一边还需要抬头看到底队伍排到你了没有,如果把打电话和观察排队的位置看成是程序的两个操作的话,这个程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的。
(4)异步非阻塞形式:效率更高,因为打电话是你(等待者)的事情,而通知你则是柜台(消息触发机制)的事情,程序没有在两种不同的操作中来回切换。
如,这个人突然发觉自己烟瘾犯了,需要出去抽根烟,于是他告诉点餐员说,排到我这个号码的时候麻烦到外面通知我一下,那么他就没有被阻塞在这个等待的操作上面,自然这个就是异步+非阻塞的方式了。
4.multiprocessing模块(包) Process模块:
准确的说,multiprocess不是一个模块而是python中一个操作、管理进程的包。 之所以叫multi是取自multiple的多功能的意思,在这个包中几乎包含了和进程有关的所有子模块。
process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建
Process类中参数的介绍:
1 group参数未使用,值始终为None
2 target表示调用对象,即子进程要执行的任务
3 args表示调用对象的位置参数元组,args=(1,2,'egon',)
4 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18}
5 name为子进程的名称
Process类中的方法介绍:
1 p.start():启动进程,并调用该子进程中的p.run()
2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
3 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
4 p.is_alive():如果p仍然运行,返回True
5 p.join([timeout]): 主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import time 2 from multiprocessing import Process 3 4 5 def func1(n,m): 6 print('我是func1') 7 print('我是%s'%n) 8 time.sleep(1) 9 print(m) 10 11 12 def func2(): 13 time.sleep(2) 14 print('我是func2') 15 16 17 if __name__ == '__main__': 18 # target表示调用对象,即子进程要执行的任务 19 # args表示调用对象的位置参数元组,args = (1, 2,) 20 # kwargs表示调用对象的字典,kwargs={'name':'egon','age':18} 21 22 # p1 = Process(target=func1,args=(10,20,)) 23 p1 = Process(target=func1,kwargs={'n':10,'m':20}) 24 p2 = Process(target=func2) 25 26 p1.start() 27 p2.start() 28 print('主程序运行到这里了') 29 p1.join() # 阻塞,等待1号子程序运行结束 30 p2.join() # 等待2号子程序运行结束 31 print('主程序运行结束')
5.进程的两种创建方法和隔离验证
两种创建方法
1 import time 2 from multiprocessing import Process 3 4 5 def func1(): 6 print('我是func1') 7 8 # 直接创建 9 # p = Process(target=func1) 10 # p.start() 11 12 13 # 面向对象方式创建 14 class MyProcess(Process): # 自定义对象创建进程必须继承Process父类 15 def __init__(self,n): 16 super().__init__() # super()拿到父类的__init__()避免重置父类 17 self.n = n 18 19 def run(self): # 必须有run方法,没有虽不会报错,但父类run里是pass,不重写run则为空 20 time.sleep(2) 21 print(self.n) 22 23 24 if __name__ == '__main__': # Windows下必须写这句 避免重复调用 25 p = MyProcess(10) 26 p.start() 27 28 print('主进程结束')
进程之间的隔离验证
1 import time 2 from multiprocessing import Process 3 4 num = 100 5 def func(): 6 global num 7 num = 66 8 print('我是func>>>',num) 9 10 11 if __name__ == '__main__': 12 13 # 所有的子进程异步执行 14 p_list = [] 15 for i in range(10): 16 p = Process(target=func) 17 p.start() 18 p.join() 19 p_list.append(p) 20 21 for pp in p_list: 22 pp.join() 23 24 # 所有的子进程全部执行完之后,再执行主进程(主进程运行很快),值不一样则证明空间隔离 25 26 print('主程序num:',num) 27 print('主程序执行结束')
6.进程对象的其他方法了解:
terminate,is_alive
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 进程对象的其他方法一:terminate,is_alive 2 from multiprocessing import Process 3 import time 4 5 6 class Piao(Process): 7 def __init__(self,name): 8 self.name=name 9 super().__init__() 10 11 def run(self): 12 print('%s is 打飞机' %self.name) 13 # s = input('???') # 别忘了pycharm下子进程中不能input输入,会报错EOFError: EOF when reading a line,因为子进程中没有像我们主进程这样的在pycharm下的控制台可以输入东西的地方 14 time.sleep(2) 15 print('%s is 打飞机结束' %self.name) 16 17 18 if __name__ == '__main__': 19 p1 = Piao('太白') 20 p1.start() 21 time.sleep(3) 22 p1.terminate() # 关闭进程,不会立即关闭,有个等着操作系统去关闭这个进程的时间,所以is_alive立刻查看的结果可能还是存活,但是稍微等一会,就被关掉了 23 print(p1.is_alive()) # 可能结果为True 24 print('等会。。。。') 25 time.sleep(1) 26 print(p1.is_alive()) # 结果一定为False
name pid
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from multiprocessing import Process 2 import time 3 import random 4 5 6 class Piao(Process): 7 def __init__(self,name): 8 # self.name=name 9 # super().__init__() #Process的__init__方法会执行self.name=Piao-1, 10 # #所以加到这里,会覆盖我们的self.name=name 11 12 # 为我们开启的进程设置名字的做法 13 super().__init__() 14 self.name=name 15 16 def run(self): 17 print('%s is piaoing' %self.name) 18 time.sleep(random.randrange(1,3)) 19 print('%s is piao end' %self.name) 20 21 22 if __name__ == '__main__': 23 24 p = Piao('egon') 25 p.start() 26 print('开始') 27 print(p.pid) # 查看pid 28 print(p.name) # 查看name