day 20 Process类、进程锁、模拟抢票
昨日回顾
1.基于socket写TCP的客户端和服务端
-加入链接循环
-加入通信循环
-客户端主动断开——> 服务端一直收空
-客户端强制断开——> 服务端会报错
-同一时刻,只能有一个客户端与服务端交互
2.基于UDP的客户端和服务端
-数据不可靠,应用场景比较少
3.并发编程(进程、线程、协程)
4.进程:
-资源分配的最小单位,线程是cpu调度的最小单位
-食谱:程序
-拿到食谱做饭的过程,叫进程
-进程:程序运行的过程,一堆数据+做一件事的过程的集合
5.python中如何开启进程
-multiprocessing中的Process
- # 开一个进程,执行task函数
p = Process(target=task)
# 进程执行起来(开启一个进程执行,需要时间)
p.start()
今日内容
1.进程调度算法(了解)
-先来先服务调度算法
-短作业优先调度算法
-时间片轮转法
-多级反馈队列
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=('lem', 18))
p.start()
print(p.name)
# group=None,
# target=None, 要执行的任务,函数
# name=None, 进程名
# args=(), 以位置参数给任务(函数)传递参数
# kwargs={}, 以关键字参数给任务(函数)传递参数
4.Process类的方法,属性(重点)
p = Process(target=task, args=('lem', 18))
p.start() # 启动进程,必须调用start
p.run() # 实际进程在执行的时候,执行的是run方法,但是调用run不会开进程
p.join() # 主进程等待子进程执行完成
p.terminate() # 通知操作系统去杀死p这个进程,需要时间
p.is_alive() # 查看进程是否存活
print(p.name) # 进程名
print(p.pid) # 进程id号
p.daemon = True # 主进程结束,子进程也结束,必须在start之前调用
主进程和子进程的进程号
from multiprocessing import Process
import os
def task(name, age):
print("p进程的id号",os.getpid()) # 当前进程id号
print("p进程的父进程也就是主进程的id号",os.getppid()) # 当前进程父进程id号
if __name__ == '__main__':
p = Process(target=task, args=('lem', 18))
p.start()
print("p进程的id号",p.pid)
print("主进程的id号",os.getpid())
print("主进程的父进程的id号(pycharm)",os.getppid())
def task1(i):
time.sleep(1)
print("task1", i)
if __name__ == '__main__':
t1 = time.time()
ll = []
for i in range(5):
p1 = Process(target=task1, args=(i,))
p1.start()
ll.append(p1)
for p in ll:
p.join()
print("主进程")
print(time.time()-t1)
"""
开启多个进程,
如果想等待多个进程同时执行完,先把进程开启完成,再统一join
"""
开启进程的另一种方式
import time
from multiprocessing import Process
import os
# 另一种开启进程的方式
# 通过继承Process类的方式来实现,重写run方法
class MyProcess(Process):
def __init__(self, name1, age):
super().__init__()
self.name1 = name1
self.age = age
def run(self) -> None:
time.sleep(2)
print(self.name1)
print(self.name)
print(self.age)
if __name__ == '__main__':
p = MyProcess('lem', 18)
p.start() # 调用p.start(),不要调用run()
进程间的数据是隔离的
import time
from multiprocessing import Process
import os
def task():
print("task")
global n
n = 100
print("子进程", n)
if __name__ == '__main__':
n = 10 # 在主进程定义n=10
## 如果这样写,n会被改掉
# task()
# print(n)
p = Process(target=task)
p.start()
print("主进程", n)
5.进程同步(进程锁)(次重点)
import json
import time
from multiprocessing import Process, Lock
# 不加锁
# 查询票剩余数量
def check(i):
with open('ticket', 'r') as f:
data = json.load(f)
print(f"{i}正在查票,票的剩余数量为{data['count']}张")
if data['count'] > 0:
return data
def write(dic):
with open('ticket', 'w') as f:
json.dump(dic, f)
# 抢票,票的数量减一
def buy(i):
data = check(i)
time.sleep(1) # 模拟查票延迟
if data:
data['count'] -= 1
time.sleep(1) # 模拟买票延迟
write(data)
print(f"{i}购票成功")
else:
print(f"{i}购票失败")
def task(i, lock):
res = check(i)
if res:
lock.acquire()
buy(i)
lock.release()
if __name__ == '__main__':
lock = Lock()
for i in range(10):
p = Process(target=task, args=(i, lock))
p.start()