2019/12/26 01-多进程编程

多线程和多进程都是并发的解决方案,往往都是利用资源,一个不够多个来凑,就是水平扩展的方案,对于我们来讲,计算机的资源有可能的,更多的去利用,多线程本身的问题和GIL的存在,在使用计算机的时候带来一些问题,不能充分利用资源。
突破GIL的锁,就可以使用多进程,当cpu密集型的时候,就算吧GIL的时间全部用完了,然后去唤醒等待中的线程,等待中的线程,还没有被唤醒,(之前的线程用完就是就绪的)谁就绪的就直接继续,其他线程还没醒来就继续睡,所以很难交替的来运行,(有些线程很难被调度到,一旦被调度到,就反复被调度,其他线程睡觉,GIL要求再同一个时刻只能在某一个cpu上,只能有一个线程在执行)
想办法绕过GIL,就可以用多进程
2019/12/26 01-多进程编程
多进程可以不局限在某一台机器上,可以跨操作系统(网络编程),这就是分布式的雏形。
注意:多进程,每个进程是独立的国家,都认为自己独占所有领土(所有cpu资源),每个进程都认为,资源归它所有,每个进程都想充分利用计算机资源,进程间的数据不随便共享,进程本身是隔离的,数据共享不如进程里方便,进程内,线程可以共享数据,线程可以共同使用进程里的数据。
多进程可以尽量充分的利用资源,操作系统跑的进程数需要合理,合理使用计算机资源

虽然线程比进程轻量,但是合理使用多进程和多线程
threading多线程
multiprocessing 多进程

这是开启5个线程一个个跑 2019/12/26 01-多进程编程
如果在python中有GIL锁,多线程跑下来和单线程顺序执行一个效果 2019/12/26 01-多进程编程
进程的给的target目标函数,进程启动的时候里面启动一个线程(相当于主线程,主线程跑一个函数),name进程名,args。kwargs
(主线程退出的时候,也需要看看还有没有none daemon线程,如果都是daemon的,就全部结束掉,主线程结束了,进程退出)
deamon可以在thread初始的时候修改,也可以set-daemon(检测心跳包,一般都会用daemon)

进程process,要提供target,name,没有daemon概念,启动进程,进程启动后,放在一个容器中 2019/12/26 01-多进程编程
然后遍历容器,join,当前进程必须等待这个进程 2019/12/26 01-多进程编程
2019/12/26 01-多进程编程
运行时错误,main模块里有一些东西
2019/12/26 01-多进程编程

** #####上面是定义区,多进程的启动,要写啊哦主模块里 ** 2019/12/26 01-多进程编程
多线程跑的时候,由于GIL,导致只能在一个时间只有一个线程在一个cpu上跑2019/12/26 01-多进程编程
78秒就结束了2019/12/26 01-多进程编程
有一个进程是跑主线程,这个线程的主线程中启动了5个新的进程,windows是平行关系,linux下未必是、。通过这样可以充分利用资源,进程是独立国家,尽可能去使用资源,进程都认为自己独占计算机资源 2019/12/26 01-多进程编程
5个进程,8个cpu都这么高,进程,调度的时候,被调度到不同的cpu上去了,每个cpu都有这样的机会(如果cpu绑定了就不会出现这样的情况了,如果绑了5个,有三个是闲着的)
绑定cpu的好处就是,(register 寄存器,缓存cache寄存器是把指令到cpu,cpu就近调用来计算,计算后扔到缓存或者内存)这个缓存是cpu缓存(有一级缓存,二级缓存,三级缓存,一般常见的三级缓存是多核共享,如果绑定了,数据在一二级缓存都有,就不用去内存里找了,如果一二级缓存里没有,就需要从内存里搬进来,速度就慢)cpu绑定是为了多核有一二级缓存的。
2019/12/26 01-多进程编程
刚才的程序跑的时候,将进程已经调度到了不同的cpu上跑,而且,显示 起来,真的同时在跑,因为GIL管不住你了,5个进程都是独自在跑,这样就可以充分利用cpu资源。
进程是资源管理单位

2019/12/26 01-多进程编程
python之所以称为简单,给的所有编程接口基本一样,多线程和多进程一本一样,换个类而已,但是不可以用多线程的锁来管多进程。,所以之前的技术是线程同步技术(都在threading模块下)
线程的同步到threading模块下
multiprocessing处理的是多进程的(多进程的同步)cpu密集型推荐使用多进程
2019/12/26 01-多进程编程
2019/12/26 01-多进程编程
运行多进程应该加这么一句
2019/12/26 01-多进程编程2019/12/26 01-多进程编程
多进程对于cpu依赖很高,不能让cpu的频率达到100%,一般到80,不能再高了
2019/12/26 01-多进程编程
每个进程在当下环境中都有PID,都是唯一的
每个进程都有退出状态码 exitcode 只要是0都是正常
进程可以中止 terminate()
(python线程,要么执行完,要么抛出异常,要么没执行完成,是daemon的,主线程直接关闭了)
对于进程来讲是可以中止的,线程中同步的概念可以用,因为在进程中有类似的概念。
但是线程的库,在进程里是用不了的
2019/12/26 01-多进程编程
**同步的类是一样的,但是是在不同模块下的类,使用方法一样,start,join这样的,进程的代价,高于线程数据共享 **

2019/12/26 01-多进程编程
除了提供进程间的通讯,进程间的通讯的queue在multiprocessing里面,线程中的queue在queue模块里,是给线程用的multipeocessing的queue是给进程间的队列用到
现在可能都用网络了,不用它,就用第三发工具了kafka这样的
2019/12/26 01-多进程编程
进程间通讯,相当于国与国通讯,比较麻烦,进程间通讯,数据需要先序列化,收到数据反序列化,序列化和反序列化时比较耗时的

数据的线程安全问题,每个进程中没有实现多线程,GIL可以说没什么用(每个进程就跑一个线程,就没什么安全不安全了)
2019/12/26 01-多进程编程

进程间同步,一般网络编程,就需要第三方队列,锁一般都是分布式锁

进程池,类似泳道,规定你跑几个,进程开辟比较麻烦,用完之后放在那里,可以反复链接
2019/12/26 01-多进程编程
同步阻塞方法
2019/12/26 01-多进程编程
async异步,这个是一个异步的方法,callback回调(我来执行你的东西)
回调是执行你这个,在时机成熟的时候,在条件满足的时候,由他来调用你的函数,

2019/12/26 01-多进程编程2019/12/26 01-多进程编程
终止工作
2019/12/26 01-多进程编程
在主线程阻塞等待子进程的退出,join方法要在close或terminate之后使用
2019/12/26 01-多进程编程
函数,参数,callback2019/12/26 01-多进程编程callback,就是最后要执行的东西
上面是自己开辟进程
下面是给池子派了5个任务

2019/12/26 01-多进程编程
join,当前的运行的主进程就会等池子里的任务结束,池子里任务不结束,就会阻塞2019/12/26 01-多进程编程
使用前必close或停用2019/12/26 01-多进程编程2019/12/26 01-多进程编程
阻塞等着下面的进程跑
2019/12/26 01-多进程编程
用池子,等于保护整个资源
2019/12/26 01-多进程编程
现在进行下改变,第一个进程起来,立马就阻塞在34行,阻塞完成,下一个进程跑,相当于单线程串起来在跑
2019/12/26 01-多进程编程
一直阻塞到循环结束为止,一般用异步,异步非阻塞,不需要等待
2019/12/26 01-多进程编程2019/12/26 01-多进程编程
processName,N要大写,否则报错,2019/12/26 01-多进程编程2019/12/26 01-多进程编程2019/12/26 01-多进程编程加个回调试试
2019/12/26 01-多进程编程
运行
2019/12/26 01-多进程编程2019/12/26 01-多进程编程2019/12/26 01-多进程编程
增加一个返回值
2019/12/26 01-多进程编程
异步方法可以通过callback拿回返回值,整个函数要求要一参,整个参数是传返回值给你2019/12/26 01-多进程编程2019/12/26 01-多进程编程
可以把进程返回的结果拿到,用callback+异步执行方式,
多进程和多线程的选择:
1.cpu密集型的时候cpython使用到了GIL,多线程的时候锁相互竞争,且多核优势不能发挥,python多进程效率更高。
2.IO密集型适合使用多线程,可以减少多进程间IO的序列化开销。且在IO等待的适合,切换到切他线程继续执行,效率不错。

2019/12/26 01-多进程编程
nginx是典型的应用,worker进程一般为了提高效率,增加cpu绑定,工作进程不会超过cpu的数目,master一般只管workr,worker进程是进行网络通信,磁盘数据读写,要大量使用IO,worker内部是多线程写的,提高并发能力。
启动多个进程,尽量占用cpu,然后再每个进程内合理开启线程,多线程核IO是紧密捆绑在一起的

2019/12/26 01-多进程编程
多线程和多进程都是混着使用的