基于TCP的大文件 上传 # 注意是上传 客户端: 1、制作字典报头 2、发送报头 3、发送字典 4、发送真实数据 服务端: 1、接收报头,从报头中获取字典长度 2、获取字典长度 3、接收字典,从字典中获取真实数据的长度 4、接收真实数据 socketserver模块: # (劳保) 使TCP能够实现并发 UDP协议: 1、不需要建立连接 2、服务端不启动也可以发送数据 3、UDP协议不存在粘包问题 4、可以实现并发 操作系统发展史: 1、穿孔卡带 2、磁带 3、批处理 目的:都是为了提高CPU利用率 多道技术: 空间上的复用: 多个程序共用一台计算机 时间上的复用: (洗衣服,做饭,烧水) CPU会在多个程序中来回切换的执行程序 CPU在两种情况下会切换到别的程序: 1、一个程序占用CPU时间过长 2、遇到IO行为 并发:看起来像同时运行就是并发 并行:真正的同时运行
今日内容
1、进程理论 2、同步和异步 | 阻塞与非阻塞 3、开启进程的两种方式(***) 4、进程对象的join方法(***) 5、进程之间内存隔离(***) 6、进程对象其他相关方法 7、僵尸进程与孤儿进程 8、守护进程 9、互斥锁(***) 锁千万不要随意去用
一、进程理论
进程:正在运行的程序 进程是一个实体,每一个进程都有其专有的名称空间 # 进程三态转换图
二、同步和异步 | 阻塞与非阻塞
这是两对 独立 且 不同 的概念 同步和异步:针对任务的提交方式 同步:提交任务之后,原地等待任务返回的结果 异步:提交任务之后,不等待任务的返回结果,直接运行下一行代码 阻塞与非阻塞:针对程序的运行状态 阻塞:遇到IO操作 >>> 阻塞态 # 进程三态状态转换图 非阻塞:就绪或者运行态 >>> 就绪态,运行态
三、开启进程的两种方式
方法一: from multiprocessing import Process import time def task(name): print('%s is running' % name) time.sleep(3) print('%s is done' % name) # 在windows系统中,创建进程会将代码以模块的方式从头到尾运行一遍 # 所以一定要写在main下面 if __name__ == '__main__': # 注意 targe = task() 这后面的函数加括号意思就是优先级最高,立刻执行 p1 = Process(target=task, args=('egon', )) # 实例化Process对象 p1.start() # 告诉操作系统创建一个进程 print('主程序') 方法二: from multiprocessing import Process import time class Myprocess(Process): # 重写Proess中的task方法 def __init__(self, name): super().__init__(slef): self.name = name # 重写的类中必须定义一个run方法 def run(self): # 既上一个方法中的 task 方法 print('%s is runnning' % self.name) time.sleep(3) print('%s is done' % self.name) if __name__ == '__main__': p1 = Myprocess('egon') # 实例化重写方法后的对象 p1.start() # 告诉操作系统创建一个进程 print('主程序')
四、进程对象的join方法
from multiprocessing import Process import time def task(name): print('%s is running' % name) time.sleep(3) print('%s is done' % name) if __name__ == '__main__': p1 = Process(target=task, args=('egon', )) p1.start() # 告诉操作系统创建一个进程 print('主程序') run==> 主程序 egon is running egon is done # 以上的代码会出现 子程序还没有运行结束 而 主程序已经结束了 # 有时,主程序需要接收子程序结束时的返回值,那么就需要等子进程结束后在运行主程序 # 使用join方法,既: if __name__ == '__main__': p1 = Process(target=task, args=('egon', )) p1.start() # 告诉操作系统创建一个进程 p1.join() # 意为等待程序p1运行结束,否则堵塞在这,同时join方法会清理子程序的pid地址和其他数据 print('主程序') run==> egon is running egon is done 主程序
五 、进程之间内存隔离
测试代码: from multiprocessing import Process num = 1 def task(): gobal num num = 100 if __name__ == '__main__': p1 = Process(target=task) p1.start() p1.join() print('主程序', x) run==> 主程序 1
六、进程对象其他相关方法
from multiprocessing import Process, current_process import time, os def task(): # 获取pid(进程地址)的方法一:current_process().pid print('%s is running' % current_process().pid) time.sleep(3) # 获取pid(进程地址)的方法二:os.getpid() print('%s is done' % os.getpid()) if __name__ == '__main__': p1 = Process(target=tast) p1.start() # p1.terminate() # 杀死子进程 # time.dleep(0.1) # 给操作系统关闭子程序的时间 # print(p1.is_alive()) print('主程序') run==> 主程序 1768 is running 1768 is done
七、僵尸进程与孤儿进程
两种情况下会回收子进程的pid等信息 1.父进程正常结束 2.join方法 孤儿进程:父进程意外意外死亡 linux下: init孤儿福利院;用来挥手孤儿进程所占用的资源 ps aux |grep 'Z'
八、守护进程
from multiprocessing import Process import time def task(name): print('%s 正活着'%name) time.sleep(3) print('%s 正常死亡'%name) if __name__ == '__main__': p = Process(target=task,args=('egon总管',)) p.daemon = True # 必须在p.start开启进程命令之前声明 成为主程序的守护进程 p.start() print('皇帝jason正在死亡')
九、互斥锁(锁千万不要随便去用)
牺牲了效率但是保证了数据的安全 锁一定要在主进程中创建,给子进程去用 解决多个进程操作同一份数据,造成数据不安全的情况 加锁会将并发变成串行 锁通常用在对数据操作的部分,并不是对进程全程加锁 mutex.acquire() # 抢锁 一把锁不能同时被多个人使用,没有抢到的人,就一直等待锁释放 buy(i) mutex.release() # 释放锁 抢票实例: from multiprocessing import Process,Lock import json import time import random def search(i): with open('info','r',encoding='utf-8') as f: data = json.load(f) print('用户查询余票数:%s'%data.get('ticket')) def buy(i): # 买票之前还得先查有没有票! with open('info','r',encoding='utf-8') as f: # 余票信息在文件'info'中 data = json.load(f) time.sleep(random.randint(1,3)) # 模拟网络延迟 if data.get('ticket') >0: # 判断余票信息 data['ticket'] -= 1 # 买票==>更新余票信息 with open('info','w',encoding='utf-8') as f: json.dump(data,f) print('用户%s抢票成功'%i) else: print("用户%s查询余票为0"%i) def run(i,mutex): search(i) # 查询余票方法 mutex.acquire() # 抢锁 一把锁不能同时被多个人使用,没有抢到的人,就一直等待锁释放 buy(i) # 抢票方法 mutex.release() # 释放锁 if __name__ == '__main__': mutex = Lock() # 创建锁 for i in range(10): p = Process(target=run,args=(i,mutex)) p.start()