进程理论知识
一、什么是进程
程序:静态的,不运行的就是程序
进程:运行起来的程序就是进程
进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展开的。
没有进程的抽象,现代计算机将不复存在。
二、进程调度
要想多个进程交替运行,操作系统必须对这些进程进行调度,这个调度也不是随即进行的,而是需要遵循一定的法则,由此就有了进程的调度算法。
先来先服务调度算法
短作业优先调度算法
时间片轮转法
多级反馈队列
三、进程的并行与并发
并行 : 并行是指两者同时执行,比如赛跑,两个人都在不停的往前跑;(资源够用,比如三个线程,四核的CPU )
并发 : 并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率。
区别:
并行:是从微观上,也就是在一个精确的时间片刻,有不同的程序在执行,这就要求必须有多个处理器。 有多个CPU在同时执行任务
并发:是从宏观上,在一个时间段上可以看出是同时执行的,比如一个处理器同时处理多个session。 只有一个CPU,交替执行多个任务
四、同步异步阻塞非阻塞
1.进程三态
2.同步和异步
同步:先洗衣服再做饭 串行 顺序执行
3.同步阻塞和异步阻塞
4.同步非阻塞和异步非阻塞
五、进程的创建与结束
1.创建新进程
所有的进程都是通过它的父进程来创建的。

2.进程的结束
进程操作(代码)
为了方便大家归类记忆,我将这部分大致分为四个部分:创建进程部分,进程同步部分,进程间通信、进程之间数据共享,进程池部分
一、创建进程-----Process模块
注意:
if __name__ == '__main__' :
# 使用python都是调用操作系统的命令来启动进程
# 同样使用python 不同的操作系统的操作时不同的
# 对于Windows来说,必须加if __name__ == '__main__' :
# 对于linux,ios来说,不必须加if __name__ == '__main__' :
1.如何开启一个子进程
multiprocessing.Process
# 第一种创建方式
实例化创建一个进程
start开启一个进程
# 第二种方式(在下面的 7 里)
采用面向对象的形式来创建进程
继承Process
重写run方法
如果要传递参数:自定义__init__,需要执行父类的__init__方法
import os from multiprocessing import Process def func(): print('我的pid:%s,父进程的pid:%s' % (os.getpid(),os.getppid())) # 3. 我的pid:10552,父进程的pid:12652 if __name__ == '__main__': print(os.getpid(),os.getppid()) # 1. 12652(父进程,即当前python运行程序) 11400(爷爷进程,即pycharm) p = Process(target=func) # 创建了一个进程对象 p.start() # 开启了一个子进程 向操作系统提交了一个开启一个子进程的申请 # 2. 启动子进程之后,运行func下面的代码,即子进程
2.进程与进程之间有什么关系?
父进程必须要等待子进程结束之后回收子进程的资源
异步:父子进程之间的工作是互不干扰的
import os import time from multiprocessing import Process def func(): time.sleep(1) print('我的pid:%s,父进程的pid:%s' % (os.getpid(),os.getppid())) # 3. 我的pid:6512,父进程的pid:5588 if __name__ == '__main__': print(os.getpid(),os.getppid()) # 1. 5588 1440 p = Process(target=func) # 创建了一个进程对象 p.start() # 开启了一个自己进程 print('主进程代码结束') # 2. 主进程代码结束
注意:p.start() 只是向操作系统提交了一个开启一个子进程的申请,所以开启子进程需要一定的时间开销;而从上往下按顺序执行是很快的,所以 print('主进程代码结束')要先打印
3.进程有什么特点?
①父进程必须要等待子进程结束之后回收子进程的资源
②进程与进程之间数据隔离
③进程与进程之间是异步的,有异步的特点-----并发
import os import time from multiprocessing import Process n = 0 def func(): global n n = 100 time.sleep(1) print('我的pid:%s,父进程的pid:%s' % (os.getpid(),os.getppid())) # 3. if __name__ == '__main__': print(os.getpid(),os.getppid()) # 1. p = Process(target=func) # 创建了一个进程对象 p.start() # 开启了一个自己进程 time.sleep(1) print('主进程代码结束') # 2. 因为开启进程是非常慢的,而按顺序往下执行时非常快的(要是睡时间较长的话就是开启进程比较快了) time.sleep(4) print('n:',n)
4.子进程传参数
import os import time from multiprocessing import Process n = 0 def func(num): global n n = 100 print(num) # 3. time.sleep(1) print('我的pid:%s,父进程的pid:%s' % (os.getpid(),os.getppid())) # 4. if __name__ == '__main__': print(os.getpid(),os.getppid()) # 1. p = Process(target=func,args=(666,)) # 创建了一个进程对象 参数必须传一个可迭代的,一般情况下传元组 p.start() # 开启了一个自己进程 print('主进程代码结束') # 2 time.sleep(5) print('n:',n) # 5.
5.子进程有返回值?
进程与进程之间数据隔离,不能直接获取到子进程执行的函数的返回值。
# 子进程的执行结果父进程获取不到
# 那要是父进程依赖子进程的执行结果呢?父进程如何获取到子进程的执行结果?
# 父子进程之间通过socket通信
6. join()方法---- 使进程由异步变为同步 -------- 一批任务使用join,一个子进程没必要用join
主进程需要在子进程都运行结束之后再做某件事情,用join对子进程进行控制
import time import random from multiprocessing import Process def wahaha(num): print(num) time.sleep(random.random()) print(num * '-') if __name__ == '__main__': p = Process(target=wahaha,args=(1,)) p.start() p.join() # 一直阻塞直到这个子进程执行完毕 print('结束')
开启多个子进程,将全部p放入列表后,遍历列表,对每个p进行join阻塞
import time import random from multiprocessing import Process def wahaha(num): print(num) time.sleep(random.random()) print(num * '-') if __name__ == '__main__': p_lst = [] for i in range(10): p = Process(target=wahaha,args=(i,)) p.start() # 启动进程是操作系统来调度的,至于他先调度谁后调度谁,不是人可以控制的 p_lst.append(p) for p in p_lst: p.join() print('结束')
7.面向对象开启子进程
不传参数
import time from multiprocessing import Process class MyProcess(Process): def run(self): time.sleep(1) print('wahaha') if __name__ == '__main__': for i in range(10): MyProcess().start()
传参数
import time from multiprocessing import Process class MyProcess(Process): def __init__(self,name): super().__init__() # 执行父类中的同名方法: self.name = name def run(self): time.sleep(1) print('%s wahaha' % self.name) if __name__ == '__main__': for i in range(10): MyProcess('alex').start()
8.主进程结束之后,我不想让我的子进程运行了,怎么做?
terminate 非阻塞
非阻塞的原因是:terminate之后子进程不会立马被杀死,一定时间后,才会被杀死。
import time from multiprocessing import Process def wahaha(): i = 0 while i < 5: print('第%s秒' % i) time.sleep(1) i += 1 if __name__ == '__main__': p = Process(target=wahaha) p.start() time.sleep(3) print('主进程') print(p.is_alive()) # 判断一个子进程是否活着 p.terminate() # 结束一个子进程 print(p.is_alive()) # 判断一个子进程是否活着 time.sleep(0.1) print(p.is_alive()) # 判断一个子进程是否活着
9.守护进程
注意:只能守护主进程的代码,不能守护整个进程
作用:报活
① 守护进程的属性,默认是False,如果设置成True,就表示设置这个子进程为一个守护进程
② 设置守护进程的操作应该在开启子进程之前
③ 设置成守护进程之后,会有什么效果呢?
守护进程会在主进程的代码执行完毕之后直接结束,无论自己是否执行完毕
import time from multiprocessing import Process def func(): while True: print('is alive') time.sleep(0.5) if __name__ == '__main__': p = Process(target=func) p.daemon = True # 这个p进程就成为守护进程了 p.start() time.sleep(3) print('主进程')
import time from multiprocessing import Process def func(): while True: print('is alive') time.sleep(0.5) def wahaha(): i = 0 while i < 5: print('第%s秒' % i) time.sleep(1) i += 1 if __name__ == '__main__': Process(target=wahaha).start() p = Process(target=func) p.daemon = True # 这个p进程就成为守护进程了 p.start() time.sleep(3) print('主进程')
如果非要等到子进程(守护进程之外的子进程)结束守护进程才结束,怎么做?
对子进程加join
import time from multiprocessing import Process def func(): while True: print('is alive') time.sleep(0.5) def wahaha(): i = 0 while i < 5: print('第%s秒' % i) time.sleep(1) i += 1 if __name__ == '__main__': p2 = Process(target=wahaha) p2.start() p = Process(target=func) p.daemon = True # 这个p进程就成为守护进程了 p.start() time.sleep(3) print('主进程') p2.join() # 守护进程会等待p2子进程结束之后才结束守护
二、进程同步
1.锁(互斥锁) ***** Lock
# 当多个进程共享一段数据的时候,数据会出现不安全的现象
# 需要加锁来维护数据的安全性。
# 维护了数据的安全,但却降低了程序的效率
# 所有的效率都是建立在数据安全的角度上的
# 但凡涉及到并发编程都要考虑数据的安全性
# 我们需要在并发部分对数据修改的操作格外小心,如果涉及到数据的不安全,就需要进行加锁控制。
# 为了避免同一段代码被多个进程同时进行,所以加上锁 from multiprocessing import Lock lock = Lock() # 创造一个锁
lock.acquire() # 想拿钥匙 print(1) lock.release() # 还钥匙 lock.acquire() # 想拿钥匙 print('拿到钥匙了') lock.release() # 还钥匙
查票的例子
# 查票的例子 import time import json from multiprocessing import Process,Lock def search(i): with open('db',encoding='utf-8')as f: dic = json.load(f) time.sleep(0.2) print('Person %s 正在查票,余票为:%s' %(i,dic['count'])) def buy(i): with open('db',encoding='utf-8')as f: dic = json.load(f) time.sleep(0.2) if dic['count'] > 0: dic['count'] -= 1 print('Person %s 买到票' % i) time.sleep(0.2) with open('db','w',encoding='utf-8')as f: json.dump(dic,f) def get_target(i,lock): search(i) lock.acquire() buy(i) lock.release() if __name__ == '__main__': lock = Lock() for i in range(10): Process(target=get_target,args=(i,lock)).start()
2.信号量(锁 + 计数器)*** Semaphore
多把钥匙对应一把锁
from multiprocessing import Semaphore sem = Semaphore(4) # 放4把钥匙 sem.acquire() # 想拿钥匙 print(1) sem.acquire() # 想拿钥匙 print(2) sem.acquire() # 想拿钥匙 print(3) sem.acquire() # 想拿钥匙 print(4) sem.release() sem.acquire() # 想拿钥匙 print(5)
KTV的例子
import time import random from multiprocessing import Process,Semaphore def ktv(sem,i): sem.acquire() # 想拿钥匙 print('%s走进ktv' % i) time.sleep(random.randint(1,3)) print('%s走出ktv' % i) sem.release() if __name__ == '__main__': sem = Semaphore(4) # 放4把钥匙 for i in range(10): p = Process(target=ktv,args=(sem,i)) p.start() # 上下文管理节省代码:节省acquire和release import time import random from multiprocessing import Process,Semaphore def ktv(sem,i): with sem: # 想拿钥匙 print('%s走进ktv' % i) time.sleep(random.randint(1,3)) print('%s走出ktv' % i) if __name__ == '__main__': sem = Semaphore(4) # 放4把钥匙 for i in range(10): p = Process(target=ktv,args=(sem,i)) p.start()
3.事件 ** Event
控制子进程执行还是阻塞的一个机制-----事件
wait方法:
在事件中有一个标志
如果这个标志是True,wait方法的执行效果就是pass
如果这个标志是False,wait方法的效果就是阻塞
判断标志状态的方法:
is_set
控制标志状态的方法:
set方法,将标志设置为True
clear方法,将标志设置为False
from multiprocessing import Event e = Event() print(e.is_set()) e.wait() # 一直阻塞,说明事件在创建之初标志的状态是False e.set() # 将标志改为True print(e.is_set()) e.wait() # 当标志为True 不阻塞
e.wait(timeout=10)
如果信号在阻塞10秒之内变为True,那么不继续阻塞直接pass,
如果信号在阻塞10秒之后状态还是没变,那么也不继续阻塞,但是状态仍是False
print(e.is_set())
无论前面的wait的timeout是否通过,我的状态都不会因此改变
import time from multiprocessing import Event,Process def func1(e): print('start funci') e.wait() print('end funci') if __name__ == '__main__': e = Event() Process(target=func1,args=(e,)).start() time.sleep(3) e.set()
import time from multiprocessing import Event,Process def func1(e): print('start func1') e.wait(1) print('end func1') if __name__ == '__main__': e = Event() Process(target=func1,args=(e,)).start() time.sleep(3) e.set()
红绿灯的例子
import time import random from multiprocessing import Event,Process def trafic_light(e): print('