上章复习回顾
黏包现象
| TCP |
| 可靠协议、流式协议 |
| TCP流式协议 会将一些短的数据打包在一起一起发送 从而产生黏包现象 |
struct模块
| import struct |
| struct.pack() 打包 |
| struct.unpack() 解析 |
| ps:将非固定长度的数字打包成固定长度 并且可以反向解析出打包前数字 |
黏包问题的解决方案
| 客户端给服务端发消息 |
| |
| 客户端 |
| 1.制作一个真实数据相关的字典 |
| 2. 将字典序列化并编码统计长度 |
| 3.利用struct模块对上述长度做打包处理 |
| 4.直接发送打包之后的数据 |
| 5.再发送字典数据 |
| 6.最后发送真实数据 |
| |
| 服务端 |
| 1.接收固定长度的报头 |
| 2.利用struct模块反向解析出字典数据的长度 |
| 3.接收字典数据并处理成字典 |
| 4.根据字典中的信息接收真实数据 |
操作系统发展史
| 1.穿孔卡片 |
| 2.联机批处理系统 |
| 3.脱机批处理系统 |
| ps:CPU利用率的发展史 |
多道技术
| 单道技术 |
| 排队执行 效率很低 |
| 多道技术 |
| 并发效果 大大提升CPU的使用率 |
| |
| 切换+保存工作 |
| 切换 |
| 1.程序有IO操作 |
| 2.程序长时间占用 |
| 保存状态 |
进程理论
| 进程:正在运行的程序 |
| |
| 进程调度算法 |
| 1.先来先服务 |
| 2.短作业优先 |
| 3.时间片轮转法+多级反馈队列 |
并行与并发
| 并行 |
| 多个任务同时执行 |
| 并发 |
| 看上去像同时执行 |
| 高并发:评估程序同时服务客户端数量的能力 |
进程的三状态
本章内容概要
同步与异步
| 用来表达任务的提交方式 |
| |
| |
| 同步 |
| 提交完任务之后原地等待任务的返回结果 期间不做任何事 |
| 异步 |
| 提交完任务之后不愿原地等待任务的返回结果 直接去做其他操作 有结果自动通知 |
阻塞与非阻塞
| 用来表达任务的执行状态 |
| |
| 阻塞 |
| 阻塞态 |
| 非阻塞 |
| 就绪态、运行态 |
综合使用
| 同步阻塞 |
| 同步非阻塞 |
| 异步阻塞 |
| 异步非阻塞(********) 效率最高 |
创建进程的多种方式
| """ |
| 1.鼠标双击软件图标 |
| 2.python代码创建进程 |
| """ |
| from multiprocessing import Process |
| import time |
| |
| |
| def task(name): |
| print('task is running',name) |
| time.sleep(3) |
| print('task is over',name) |
| |
| """ |
| 在不同的操作系统中创建进程底层原理不一样 |
| windows |
| 以导入模块的形式创建进程 |
| linux/mac |
| 以拷贝代码的形式创建进程 |
| |
| """ |
| |
| |
| |
| |
| |
| |
| |
| from multiprocessing import Process |
| import time |
| |
| |
| class MyProcess(Process): |
| def __init__(self, name, age): |
| super().__init__() |
| self.name = name |
| self.age = age |
| |
| |
| def run(self): |
| print('run is running', self.name, self.age) |
| time.sleep(3) |
| print('run is over', self.name, self.age) |
| |
| |
| if __name__ == '__main__': |
| obj = MyProcess('jason', 123) |
| obj.start() |
| print('主') |
| |
进程join方法
| from multiprocessing import Process |
| |
进程间数据隔离
| 同一台计算机上的多个进程数据是严格意义上的物理隔离(默认情况下) |
| |
| from multiprocessing import Process |
| import time |
| |
| money = 1000 |
| |
| |
| def task(): |
| global money |
| money = 666 |
| print('子进程的task函数查看money', money) |
| |
| |
| if __name__ == '__main__': |
| p1 = Process(target=task) |
| p1.start() |
| time.sleep(3) |
| print(money) |
进程间通信之IPC机制
| IPC:进程间通信 |
| 消息队列:存储数据的地方 所有人都可以存 也都可以取 |
| |
| from multiprocessing import Queue |
| |
| |
| q = Queue(3) |
| |
| q.put(111) |
| |
| q.put(222) |
| q.put(333) |
| |
| |
| print(q.get()) |
| print(q.get()) |
| |
| print(q.get()) |
| |
| |
| print(q.get_nowait()) |
| |
| """ |
| full() empty() 在多进程中都不能使用!!! |
| """ |
| |
| |
| from multiprocessing import Process, Queue |
| |
| |
| def product(q): |
| q.put('子进程p添加的数据') |
| |
| def consumer(q): |
| print('子进程获取队列中的数据', q.get()) |
| |
| |
| if __name__ == '__main__': |
| q = Queue() |
| |
| |
| p1 = Process(target=consumer, args=(q,)) |
| p2 = Process(target=product, args=(q,)) |
| p1.start() |
| p2.start() |
| print('主') |
进程对象诸多方法
| 1.如何查看进程号 |
| from multiprocessing import Process, current_process |
| current_process() |
| current_process().pid |
| import os |
| os.getpid() |
| os.getppid() |
| 2.终止进程 |
| p1.terminate() |
| ps:计算机操作系统都有对应的命令可以直接杀死进程 |
| 3.判断进程是否存活 |
| p1.is_alive() |
| 4.start() |
| 5.join() |
生产者消费者模型
| """回想爬虫""" |
| 生产者 |
| 负责产生数据的'人' |
| 消费者 |
| 负责处理数据的'人' |
| |
| 该模型除了有生产者和消费者之外还必须有消息队列(只要是能够提供数据保存服务和提取服务的理论上都可以) |
互斥锁
| 模拟抢票软件 |
| |
| from multiprocessing import Process |
| import time |
| import json |
| import random |
| |
| |
| |
| def search(name): |
| with open(r'data.json', 'r', encoding='utf8') as f: |
| data = json.load(f) |
| print('%s在查票 当前余票为:%s' % (name, data.get('ticket_num'))) |
| |
| |
| |
| def buy(name): |
| |
| with open(r'data.json', 'r', encoding='utf8') as f: |
| data = json.load(f) |
| |
| time.sleep(random.randint(1, 3)) |
| |
| if data.get('ticket_num') > 0: |
| data['ticket_num'] -= 1 |
| with open(r'data.json', 'w', encoding='utf8') as f: |
| json.dump(data, f) |
| print('%s买票成功' % name) |
| else: |
| print('%s很倒霉 没有抢到票' % name) |
| |
| |
| def run(name): |
| search(name) |
| buy(name) |
| |
| |
| if __name__ == '__main__': |
| for i in range(10): |
| p = Process(target=run, args=('用户%s'%i, )) |
| p.start() |
| |
| """ |
| 多进程操作数据很可能会造成数据错乱>>>:互斥锁 |
| 互斥锁 |
| 将并发变成串行 牺牲了效率但是保障了数据的安全 |
| """ |
僵尸进程与孤儿进程
| 僵尸进程 |
| 进程执行完毕后并不会立刻销毁所有的数据 会有一些信息短暂保留下来 |
| 比如进程号、进程执行时间、进程消耗功率等给父进程查看 |
| ps:所有的进程都会变成僵尸进程 |
| 孤儿进程: |
| 子进程正常运行 父进程意外死亡 操作系统针对孤儿进程回派遣福利院管理 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构