并发编程-进程(多道技术)
并发编程
并发与串行
- 
什么是串行?
串行就是程序自上而下,按顺序一行行执行程序,且必须把当前任务执行完毕才能执行下一个程序
问题:
- 程序执行效率变低
 - 占用内存资源
 
 - 
什么是并发?
并发就是可以同时执行多个程序(本质是在不同的进程间快速切换执行,并保存程序状态) 总结就是:切换+保存
串行和并发都是程序处理任务的方式
 
为什么要用并发?
- 可以同时执行多个程序,提高了工作效率
 - 提高内存资源的利用率
 
实现并发的方式
- 多进程
 - 多线程
 - 协程
 
什么是进程?
 进程指的是正在运行的程序,是操作系统调度以及进行资源分配的基本单位 (进程就是一个资源单位)
- 
进程是怎么来的?
当把一个程序从硬盘读入内存时,进程就产生了
 - 
什么是多进程?
同一时间有多个程序被读入到内存并执行,就是多进程
 
进程来自于操作系统,有操作系统进行调度以及资源分配
多进程的实现原理其实就是操作系统调度进程的原理
多道技术 (重点)
实现原理:
- 
空间复用:
将内存划分多个区域,放入多个程序到内存中,且内存区域相互隔离(物理层面的隔离,为了保证数据安全)
 - 
时间复用:(切换+保存)
指的是操作系统会在多个进程之间做切换执行
切换任务的两种情况:
- 当一个进程遇到了IO操作时会自动切换
 - 当一个任务执行时间超过阈值会强制切换
 
在切换前必须保存状态,以便后续恢复执行
 
并发编程中的重要概念(重点)
- 
串行:程序自上而下,按顺序一个个执行
 - 
并发:在不同的人物之间快速切换
 - 
并行:真正的同时执行多个程序,需要多核CPU
三者都是处理任务的方式
 - 
阻塞: 指的是程序遇到了IO操作,无法继续执行代码时的一种状态
 - 
非阻塞:指的是程序没有遇到IO操作的一种状态
 - 
进程的三种状态
- 阻塞:释放IO操作,转换成就绪
 - 运行:遇到IO操作和运行超时,转换成阻塞;释放IO操作转换成就绪
 - 就绪:CPU调用,转换成运行
 
 
python中使用多进程的两种方式:
- 
导入 multiprocessing 中的Process类,实例化这个类,指定要执行的任务程序target
import os from multiprocessing import Process """ Process 就表示进程 为什么要开进程 """ def task(): print("this is sub process") print("sub process id %s" % os.getpid()) if __name__ == '__main__': # ######注意 开启进程的代码必须放在 ————main————判断下面 # 实例化一个进程对象 并制定他要做的事情 用函数来指定 p = Process(target=task) p.start() # 给操作系统发送消息 让它开启进程 print("this is parent process") print("parent process is: %s" % os.getpid()) print("over") - 
导入 multiprocess 中的Process类,继承这个类,覆盖run方法,将要执行的任务放入到run中开启进程是会自动执行该函数
from multiprocessing import Process import os class Downloader(Process): # def __init__(self,url,size,name): # super().__init__() # self.url = url # self.size = size # self.name = name def run(self): print(os.getpid()) pass if __name__ == '__main__': m = Downloader() m.start() print("parent over",os.getpid()) 
join函数(重点)
主要能提高子进程的优先级,使得子进程执行完成后,在执行父进程
from multiprocessing import Process
import time
def task1(name):
    for i in range(10000):
        print("%s run" % name)
def task2(name):
    for i in range(100):
        print("%s run" % name)
if __name__ == '__main__': # args 是给子进程传递的参数 必须是元组
    p1 = Process(target=task1,args=("p1",))
    p1.start()  # 向操作系统发送指令
    # p1.join()   # 让主进程 等待子进程执行完毕在继续执行
    p2 = Process(target=task2,args=("p2",))
    p2.start()  # 向操作系统发送指令
    p2.join()  # 让主进程 等待子进程执行完毕在继续执行
    p1.join()
    #需要达到的效果是 必须保证两个子进程是并发执行的 并且 over一定是在所有任务执行完毕后执行
    print("over")
进程对象的常用属性 (了解)
 # p.daemon #守护进程
    # p.join()
    # print(p.exitcode) # 获取进程的退出码   就是exit()函数中传入的值
    # print(p.is_alive())  # 查看进程是否存活
    # print("zi",p.pid) # 获取进程id
    # print(os.getpid()) #获取当前进程的编号
    # p.terminate()  #终止进程  与strat 相同的是 不会立即终止,因为操作系统有很多事情要做  
    # print(p.is_alive()) 判断进程是否存活
僵尸进程和孤儿进程
孤儿进程 当父进程已经结束 而子进程还在运行 子进程就称为孤儿进程 尤其存在的必要性,没有不良影响
僵尸进程 当一个进程已经结束了但是,它仍然还有一些数据存在 此时称之为僵尸进程
在linux中,有这么一个机制,父进程无论什么时候都可以获取到子进程的的 一些数据
子进程 任务执行完毕后,确实结束了但是仍然保留一些数据 目的是为了让父进程能够获取这些信息
linux中 可以调用waitpid来是彻底清除子进程的残留信息
python中 已经封装了处理僵尸进程的操作 ,无需关心
                    
                
                
            
        
浙公网安备 33010602011771号