进程和线程的代码实现
-
进程
-
(理论部分)
-
三态示意图
- 就绪(Ready)状态当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。
- 执行/运行(Running)状态当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。
- 阻塞(Blocked)状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。
-
同步和异步
-
两者都是关于任务提交的方式而言的:
同步:任务提交之后 原地等待的任务的执行并拿到返回结果才走 期间不做任何事(程序层面的表现就是卡住了) 单任务,按顺序执行
异步:任务提交之后 不再原地等待 而是继续执行下一行代码(结果是要的 但是是用过其他方式获取) 多任务,结束无顺序 -
-
阻塞非阻塞(描述程序的运行状态)
-
阻塞:阻塞态
非阻塞:运行态或者就绪态
-
(代码实践部分)
-
如何创建一个进程
-
from multiprocessing import Process import time def process1(name): time.sleep(1) print('%s is the best player in the world'%name) """ windows 创建进程时 会把代码当做模块自上而下一起执行 windows 执行进程时 一定要在if __name__ = '__main__' 语句中执行 否则则报错 """ if __name__ =='__main__': p = Process(target = process1,args = ('lion messi',)) # target 后面跟的是将要执行的函数名信息 args是位置参数,值得注意的是千万不要忘了加逗号 p.start() # 开启一个进程 会自顶而上的执行target中的函数体代码 print('主进程 messi nb') # 由于执行process1的进程时,遇到了time.sleep的阻塞态,子进程会等待阻塞态转换为就绪态时执行接下来的代码
在等待过程中由于子进程和主进程是异步的关系,则不在原地等待子进程执行完毕,直接执行主进程的print代码 -
多个程序同时运行并且使用join方法
-
from multiprocessing import Process import time def process1(name,i): print('%s is ready'%(name)) time.sleep(i) print('%s is running'%(name)) if __name__ == '__main__': process_list = [] start = time.time() for i in range(1,5): p = Process(target = process1,args = ('进程%s'%i,i,)) p.start() # 进程的开启没有先后顺序,只是操作系统同时创建了这几个进程 至于谁先执行代码 这个问题并不是由启动顺序决定的 process_list.append(p) for process in process_list: process.join() # p.join()的作用在于 主进程必须等待子进程运行结束后才能运行 更深层次来说 在p.join()之前的都是子进程,
必须等待之前的进程执行完才能执行接下来的进程 print('主进程') print(time.time()-start) # 可以发现时间会比最长的睡眠时间要多那么0.1-0.5秒这是因为开启每个进程都需要CPU来处理的时间, # 并且由此也可以印证几个程序都是同时开启,因此最后的运行时间才能是4s左右# 第一次开启的结果 进程3 is ready 进程1 is ready 进程4 is ready 进程1 is running 进程2 is running 进程3 is running 进程4 is running 主进程 4.219241380691528
# 第二次开启的结果 进程3 is ready 进程4 is ready 进程2 is ready 进程1 is ready 进程1 is running 进程2 is running 进程3 is running 进程4 is running 主进程 4.160238027572632 # 可以明显发现几次开启进程时,进程执行的顺序都不一样,但是阻塞态之后的运行态的输出都一样那是因为阻塞态持续的时间不一样
-
进程之间的数据是隔离的
-
from multiprocessing import Process def work(): global n n=0 # 修改全局变量的n 的取值 但是仅仅是对当前进程的内存空间的值 进行修改,并不改变其他内存空间的n的值 print('子进程内: ',n) if __name__ == '__main__': n = 100 p=Process(target=work) # 输出子进程内:0 p.start() print('主进程内: ',n) # 主进程中的n值不会被修改,因为多个进程之间的数据是存储在各自的内存空间之中,之间没有交互
# 输出主进程内:100 -
进程对象及其内置方法
-
from multiprocessing import Process import time import os def process(name): print('%s is running'%(name),'子进程的pid地址是%s'%(os.getpid()),'主进程的pid地址是%s'%(os.getppid())) time.sleep(2) print('%s is over'%(name)) if __name__ == '__main__': p = Process(target=process , args = ('messi',)) p.start() print(p.pid) # 返回该进程的pid地址 # p.terminate() # 杀死该进程 time.sleep(0.1) # 由于判断进程是否存活的方法需要一点响应时间,否则会一直返回该进程依然存活 print(p.is_alive()) # 判断该进程是否存活 如果存活 则返回True,反之则返回False print(f'主进程的pid地址是{os.getpid()},主主进程的pid地址是{os.getppid()}') # 主主进程的概念就是执行该进程的pycharm软件进程的pid地址
-