02:进程调度 --- 进程同步(进程锁)
-先来先服务调度算法
-短作业优先调度算法
-时间片轮转法
-多级反馈队列
2 同步异步,阻塞非阻塞(了解)
1 同步调用:提交了以后,一直等待结果返回
2 异步调用:提交了以后,返回一个标志,等执行完成后,有消息通知
3 同步,异步:指的是消息通知机制
4 阻塞,非阻塞:程序在等待调用结果的状态
5 同步阻塞:打电话要买书,如果电话没挂,我也一直在等待,
6 同步非阻塞:打电话买书,电话没挂,我一边干别的事,一边听一下电话
7 异步阻塞:打电话买书,电话先挂掉,过一会老板会回回来(回调),老板给回电话的过程一直在等待
8 异步非阻塞:打电话买书,电话先挂掉,过一会老板会回回来(回调),老板给回电话的过程中,在干别的事
3 Process类的参数(重点)
from multiprocessing import Process def task(name,age): print(name) print(age) if __name__ == '__main__': # p=Process(target=task,args=['lqz',18]) # p=Process(target=task,kwargs={'age':19,'name':'lqz'},name='process01') p=Process(target=task,kwargs={'age':19,'name':'lqz'}) p2=Process(target=task,kwargs={'age':19,'name':'lqz'}) p.start() p2.start() print(p.name) print(p2.name) # target=None, 你要执行的任务,函数 # name=None, 进程名 # args=(), 以位置参数给任务(函数)传递参数 # kwargs={} 以关键字的形式给任务(函数)传递参数
4 Process类的方法,属性(重点)
from multiprocessing import Process import time def task(name,age): time.sleep(10) print(name) print(age) if __name__ == '__main__': p=Process(target=task,kwargs={'age':19,'name':'lqz'}) p.start() #启动进程,必须调用start # p.run() # 实际进程在执行的时候,执行的是run方法,但是调用run不会开进程,后面我们另一种开启进程的方案使用到它 # p.join() # 等待子进程执行完成 print(p.is_alive()) #True p.terminate() # 杀死p这个进程,通知操作系统去杀死该进程 time.sleep(0.1) print(p.is_alive()) #可能还是True print('ssss') print(p.is_alive()) #就是False print(p) 掌握↓↓↓ ''' p.start() #启动进程,必须调用start p.run() # 实际进程在执行的时候,执行的是run方法,但是调用run不会开进程,后面我们另一种开启进程的方案使用到它 p.join() # 等待子进程执行完成 p.terminate() # 杀死p这个进程,通知操作系统去杀死该进程,并不是立即结束 p.is_alive() #进程是否还存活 '''
2.1 属性
from multiprocessing import Process import time def task(name,age): time.sleep(10) print(name) print(age) if __name__ == '__main__': p=Process(target=task,kwargs={'age':19,'name':'lqz'}) # p.start() # print(p.name) # 进程名字 # p.daemon=True #主进程结束,子进程也结束,必须在start之前调用 p.start() print(p.pid) # 进程id号 time.sleep(10) 掌握↓↓↓ ''' print(p.name) # 进程名字 print(p.pid) # 进程id号 p.daemon=True #主进程结束,子进程也结束,必须在start之前调用 '''
主进程和子进程的进程号
from multiprocessing import Process import time import os def task(name,age): # 如果在任务中取出进程id号,需要使用os模块 print('当前进程(子进程)id号是:',os.getpid()) #当前进程id号 print('当前进程父进程的id号是:',os.getppid()) # 当前进程父进程的id号 time.sleep(10) print(name) print(age) if __name__ == '__main__': p=Process(target=task,kwargs={'age':19,'name':'lqz'}) p.start() print('p这个进程的id号是:',p.pid) # 进程id号 print('当前进程id(主进程)号是:', os.getpid()) # 当前进程id号 print('当前进程父进程(pycharm)的id号是:', os.getppid()) # 当前进程父进程的id号 time.sleep(10) 掌握↓↓↓ ''' 如果有p对象,就是用p.pid获取进程id号 如果没有p对象,就是用os模块的 os.getpid() #当前进程id号 os.getppid() #父进程id号 '''
同时开启多个进程
from multiprocessing import Process import time import os # def task(name,age): # time.sleep(10) # print(name) # print(age) # def task1(): # time.sleep(2) # print("我是task1") # # # if __name__ == '__main__': # p=Process(target=task,kwargs={'age':19,'name':'lqz'}) # p.start() # # p1=Process(target=task1) # p1.start() # # print('主进程') import time def task1(i): time.sleep(2) print("我是task1",i) if __name__ == '__main__': ctime=time.time() ll=[] for i in range(5): p1=Process(target=task1,args=[i,]) p1.start() p1.join() #等待子进程执行完成 # ll.append(p1) # for p in ll: # p.join() [p.join()for p in ll] print('主进程') print(time.time()-ctime) 掌握↓↓↓ ''' 开启多个进程 如果想等待多个进程同时执行完,先把进程开启完成,再统一join '''
开启进程的另一种方案
### 通过继承Process类的方式来实现,重写run方法,run方法就是你要执行的任务,实例化得到对象,调用start方法开启进程 class MyProcess(Process): def __init__(self,name1,age): self.name1=name1 self.age=age # 这个必须写 super().__init__() def run(self) : time.sleep(2) print(self.name) print(self.name1) print(self.age) if __name__ == '__main__': p=MyProcess('lqz',19) p.start() #调用p.start(),不要调用run print('主进程')
进程之间数据隔离
from multiprocessing import Process import time import os def task(): print('我是task') global n n=100 print('子进程的:',n) if __name__ == '__main__': # 在主进程中定义了一个n=10 n=10 ###如果这样写,n会被改掉 # task() # print(n) ##如果这样写,n不会被改掉 p=Process(target=task) p.start() print('主进程的:',n)
5 高并发的TCP服务端
import socket from multiprocessing import Process def talk(sock,addr): print('客户端连接成功',addr) while True: try: data = sock.recv(1024) if len(data) == 0: break print('从客户端收到了:', data) sock.send(data.upper()) except Exception as e: print(e) break sock.close() if __name__ == '__main__': server = socket.socket() server.bind(('127.0.0.1', 81)) server.listen(5) while True: print('等待客户端连接') sock, addr = server.accept() p=Process(target=talk,args=[sock,addr]) p.start() server.close() from multiprocessing import Process import time import os def task(): print('我是task') global n n=100 print('子进程的:',n) if __name__ == '__main__': # 在主进程中定义了一个n=10 n=10 ###如果这样写,n会被改掉 # task() # print(n) ##如果这样写,n不会被改掉 p=Process(target=task) p.start() print('主进程的:',n)
6 进程同步(进程锁)(次重点)
import time ## 不加锁 import json from multiprocessing import Process,Lock ## 查询票余额 def check(i): with open('ticket', 'rt', encoding='utf-8') as f: res = json.load(f) print('%s:在查询票,票还剩%s张' % (i, res['count'])) if res['count'] > 0: return True ## 抢票,票的余额减一 def buy(i): with open('ticket', 'rt', encoding='utf-8') as f: res = json.load(f) time.sleep(1) # 模拟查票延迟 if res['count'] > 0: print('%s现在要买了,票数还是大于0'%i) res['count'] -= 1 time.sleep(2) # 模拟买票延迟 with open('ticket', 'wt', encoding='utf-8') as f1: json.dump(res, f1) print('%s这个人购票成功' % i) else: print('%s这个人购票失败,票不够了,买不了了' % i) def task(i,lock): res = check(i) if res: lock.acquire() buy(i) lock.release() ##模拟10个人买票 if __name__ == '__main__': lock=Lock() for i in range(10): p = Process(target=task, args=[i,lock ]) p.start()
总结
1 进程调度算法 -先来先服务 -短作业有限 -时间片轮转 -多级反馈队列 2 同步,异步;阻塞,非阻塞 -同步和异步:指的是回调方式,如果有回调,就是异步,如果同步等待就是同步 -阻塞,非阻塞:指等待消息结果时的状态,如果在等的过程中,干了别的事,就是非阻塞,如果一直等就是阻塞 3 进程类Process类,实例化的时候的参数: -target:要执行的任务 -args:以位置形式给任务传值 -kwargs:以关键字给任务传值 -name:进程名字(如果不写,会有个默认名字) 4 进程对象的属性和方法 -属性 -name -pid:进程id号,如果没有这个对象,需要借助os.getpid(),os.getppid() -daemon:守护进程,如果设置为True,主进程挂掉,这个进程也会挂掉,需要在p.start之前执行 -方法: -is_alive() 进程是否存活 -terminate() 停止该进程 -join() 等待子进程执行结束,主进程再继续执行 -start() 子进程要执行,必须调用它 -run() 真正的任务 5 开启进程的另一种方式(类的继承) 写一个类,继承Process类 重写run方法,就是你的任务 实例化得到我们写的类,调用这个类对象的.start() 6 进程间数据是隔离的 6 进程锁 -多个进程操作同一个数据(文件中的数据,而不是内存中的数据:) -lock=Lock() -加锁:lock.acquire() -解锁:lock.release()
愿君前程似锦,归来仍是少年