目标:让服务端能够支持高并发+高性能
一、 操作系统发展史
多道技术(*****) 产生背景:想要在单核下实现并发 多道技术的核心: 1、空间上的复用(具体指的是内存中同时读入多道程序,多道程序的内存空间是物理隔离) 2、时间上的复用(复用cpu的时间) 切换+保存状态=》并发 切换: 1、遇到IO切换(可以提升效率) 2、运行时间过长或者有一个优先级更高的进程抢走了cpu(反而会降低效率)
二、进程 (参考博客:https://www.cnblogs.com/linhaifeng/articles/7428874.html)
1、进程理论(*****) 1、进程与程序区别 2、并发与并行 并发:看起来同时运行,单核就可以实现并发,但是单核无法实现并行 并行:真正意义上的同时运行,一个cpu同一时刻只能做一件事 只有多核才能同时做多件事,即并行的效果 串行:按照固定的顺序一个个地执行 3、不同操作系统开启子进程的区别 4、一个进程的三种运行状态
2、开启进程的两种方式(*****)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#方式一 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__': # 在windows系统之上,开启子进程的操作一定要放到这下面 # Process(target=task,kwargs={'name':'egon'}) p=Process(target=task,args=('egon',)) p.start() # 向操作系统发送请求,操作系统会申请内存空间,然后把父进程的数据拷贝给子进程,作为子进程的初始状态 print('======主') #打印结果 # ======主 # egon is running # egon is done #方式二 from multiprocessing import Process import time class MyProcess(Process): def __init__(self,name): super(MyProcess,self).__init__() #继承父类功能 self.name=name def run(self): print('%s is running' %self.name) time.sleep(3) print('%s is done' %self.name) if __name__ == '__main__': p=MyProcess('egon') p.start() print('主') #打印结果 # 主 # egon is running # egon is done
了解:僵尸进程与孤儿进程(**):https://www.cnblogs.com/Anker/p/3271773.html
3、守护进程(**)
主进程创建守护进程
其一:守护进程会在主进程代码执行结束后就终止
其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are not allowed to have children
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止
4、互斥锁与信号量(**)
互斥锁就将并发变成一个一个的执行,牺牲了效率保证了数据安全
只有在多个任务修改共享的数据的时候才会考虑用互斥锁
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from multiprocessing import Process,Lock import time,random mutex=Lock() # 互斥锁: #强调:必须是lock.acquire()一次,然后 lock.release()释放一次,才能继续lock.acquire(),不能连续的lock.acquire() # 互斥锁vs join的区别一: # 大前提:二者的原理都是一样,都是将并发变成串行,从而保证有序 # 区别:join是按照人为指定的顺序执行,而互斥锁是所以进程平等地竞争,谁先抢到谁执行 def task1(lock): lock.acquire() # print('task1:名字是egon') time.sleep(random.randint(1,3)) print('task1:性别是male') time.sleep(random.randint(1,3)) print('task1:年龄是18') lock.release() def task2(lock): lock.acquire() print('task2:名字是alex') time.sleep(random.randint(1,3)) print('task2:性别是male') time.sleep(random.randint(1,3)) print('task2:年龄是78') lock.release() def task3(lock): lock.acquire() print('task3:名字是lxx') time.sleep(random.randint(1,3)) print('task3:性别是female') time.sleep(random.randint(1,3)) print('task3:年龄是30') lock.release() if __name__ == '__main__': p1=Process(target=task1,args=(mutex,)) p2=Process(target=task2,args=(mutex,)) p3=Process(target=task3,args=(mutex,)) # p1.start() # p1.join() # p2.start() # p2.join() # p3.start() # p3.join() p1.start() p2.start() p3.start() #打印结果 task1:名字是egon task1:性别是male task1:年龄是18 task2:名字是alex task2:性别是male task2:年龄是78 task3:名字是lxx task3:性别是female task3:年龄是30
5、IPC机制:队列,管道(*)
进程之间通信必须找到一种介质,该介质必须满足
1、是所有进程共享的
2、必须是内存空间
附加:帮我们自动处理好锁的问题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from multiprocessing import Queue q=Queue(3) #队列: #1、是内存空间 #2、自动处理锁的问题 #3、队列是先进先出,可以放任意的python数据类型 #4、队列中不应该存放很大的数据,而是一些消息级的数据 q.put('first') q.put('sencod') q.put('third') # q.put('third') print(q.get()) print(q.get()) print(q.get())
6、进程queue=管道+锁 (***)
7、生产者消费者模型(*****)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1、什么是生产者消费者模型? 模型指的是解决问题的一种套路 该模型中包含两种重要的角色: 生产者:生产数据的任务 消费者:处理数据的任务 2、什么时候用生产者消费者模型? 在程序中有明显地两类任务,一类负责生产数据,另外一个类则拿到生产的数据进行处理,此时就应该考虑使用生产者消费者模型来处理这种问题 3、为什么要用生产者消费者模型?好处? 1、将生产者与消费者解开耦合 2、平衡了生产者的生产数据的能力和消费者处理数据的能力 原理: 解耦和指的是生产者不与消费者直接打交道, 生产者可以不停地往队里里放数据 消费者可以不停地从队列里取走数据进行处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#生产者消费者模型 # 该模型中包含两类重要的角色: #1、生产者:将负责造数据的任务比喻为生产者 #2、消费者:接收生产者造出的数据来做进一步的处理,该类人物被比喻成消费者 # 实现生产者消费者模型三要素 #1、生产者 #2、消费者 #3、队列 # 什么时候用该模型: #程序中出现明显的两类任务,一类任务是负责生产,另外一类任务是负责处理生产的数据的 # 该模型的好处: # 1、实现了生产者与消费者解耦和 # 2、平衡了生产力与消费力,即生产者可以一直不停地生产,消费者可以不停地处理,因为二者 #不再直接沟通的,而是跟队列沟通 import time import random from multiprocessing import Process,Queue def consumer(name,q): while True: res=q.get() time.sleep(random.randint(1,3)) print('