Python-GIL 进程池 线程池
    5、GIL vs 互斥锁(*****)
        1、什么是GIL(Global  Interpreter  Lock)
            GIL是全局解释器锁,是加到解释器身上的,保护的就是解释器级别的数据 (比如垃圾回收的数据)
            同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码
        2 为什么需要GIL
          python 中内存管理依赖于 GC(一段用于回收内存的代码) 也需要一个线程
            除了你自己开的线程 系统还有一些内置线程   就算你的代码不会去竞争解释器  内置线程也可能会竞争
            所以必须加上锁
        3、GIL的影响
            GIl会限制同一进程的内的多个线程同一时间只能有一个运行,也就是说python一个进程内的多线线程
    无法实现并行的效果,即无法利用多核优势
            然后多核提供的优势是同一时刻有多个cpu参与计算,意味着计算性能地提升,也就是说我们的任务是
            计算密集型的情况下才需要考虑利用多核优势,此时应该开启python的多进程
            在我们的任务是IO密集型的情况下,再多的cpu对性能的提升也用处不大,也就说多核优势在IO密集型程序面前
            发挥的作用微乎其微,此时用python的多线程也是可以的
        GIL的优缺点:
            优点:
                保证Cpython解释器内存管理的线程安全
            缺点:
                同一进程内所有的线程同一时刻只能有一个执行,无法利用多核CPU
                也就说Cpython解释器的多线程无法实现并行
        (问题: 一个py程序 要想运行 必须运行解释器 解释器的工作时翻译代码 并执行
           当一个py进程中 有多个线程 线程的任务就是执行代码  意味者 多个线程都要使用解释器
           简单的说 多线程会争抢解释器的执行权
           如果是自己开的线程  多线程要访问相同数据 加锁就能解决
           但是有一写代码不是程序员写的 也确实需要共享使用 就是解释器
        GC:垃圾回收器  负责清理内存中的无用数据 清理垃圾也需要执行代码  但是GC不应该卡住用户的代码执行
            只能开线程
            GC 看到 x = 10   x = 1   准备删除10  这时候突然CPU切到用户线程  a = 10  此此时还没有问题
            紧接着 CPU 又切到GC  GC上来就删除10  在切到用户线程 a 所指向的地址被清理了 产生错误
        解决方案: 给解释器加上锁  保证GC执行期间 用户线程不能执行)
        4、GIL vs 自定义锁
            保护不同的数据就应该加不同的锁。
            相同点:都是互斥锁
            不同点:
                 GIL解释器级别锁 锁的是解释器代码
                 自定义锁 锁的是自己写的代码
            GIL 在当一个线程调用解释器时 自动加锁  在IO阻塞时或线程代码执行完毕/执行时间过长3ms时 自动解锁
            本质就是一个互斥锁,然后保护不同的数据就应该用不同的互斥锁,保护我们应用程序级别的数据必须自定义互斥锁
            有了GIL 为什么还需要自定义锁?
                GIL 不清楚什么代码会造成数据竞争问题  不知道什么地方该加
    6 Cpython的解释器下,多线程是鸡肋?*****
        多个任务是IO密集型:多线程  (IO的速度 明显要比CPU执行速度慢)
        多个任务是计算密集型:多进程
    7、死锁现象与递归锁(可重入锁),信号量(**)
      死锁?
        进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额
        所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,
                若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,
                这些永远在互相等待的进程称为死锁进程,如下就是死锁
        解决方法,递归锁,在Python中为了支持在同一线程中多次请求同一资源,python提供了可重入锁RLock。
            这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,
            从而使得资源可以被多次require。直到一个线程所有的acquire都被release,
            其他的线程才能获得资源。上面的例子如果使用RLock代替Lock,则不会发生死锁:
        mutexA=mutexB=threading.RLock() #一个线程拿到锁,counter加1,该线程内又碰到加锁的情况,
        则counter继续加1,这期间所有其他线程都只能等待,等待该线程释放所有锁,即counter递减到0为止
        死锁造成的问题.程序卡死
        一个锁不会产生死锁
        当有多个锁多个线程时会产生死锁
        a b  锁
        p k  线程
        当p 和 k 都需要a和b锁时才可能产生死锁
      递归锁(可重入锁)RLock
        同一个线程可以多次执行acquire  执行一次acquire  计数加1
        执行一次release 次数减一 执行acquire的次数需要与release的次数对应
        在执行被锁的代码时   同一个线程 不会判断次数   其他线程需要判断 计数为0才可以执行
        不是用来解决死锁的
      Semaphore信号量(了解) 常用在线程中
        信号量作用:限制同时执行被锁代码的线程数量
        案列:
        sem = semaphore(2)
        acquire
        code.....
        release
        开了十个线程 只能有两个同时执行
    8、队列queue(***)
        queue 这个queue和进程里的Queue不同 就是一个简单的容器
            队列是一种数据的容器
            特点:先进先出
        queue先进先出
        lifoqueue先进后出
        priorityqueue  优先级队列  整型表示优先级   数字越大优先级越低
        import queue
        q = queue.Queue()# 普通队列 先进先出
        q.put("a")
        q2 = queue.LifoQueue()# 堆栈队列  先进后出 后进先出  函数调用就是进栈  函数结束就出栈 递归造成栈溢出
        q3 = queue.PriorityQueue()  # 优先级队列
    9、Event事件(**)了解
    python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。
    事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,
        那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。
        是什么?
            线程间通讯的方式
        为什么用?
            简化代码
        set()设置为True
        wati()阻塞 直到为True
        clear:将“Flag”设置为False
4、池(*****)
    就是一个装进程/线程的容器
    为何要用池:
        操作系统无法无限开启进程或线程
        池作用是将进程或线程控制操作系统可承受的范围内
    什么时候用进程池: (比如 双十一)
        当程序中有多个进程时 管理变得非常麻烦
        进程池可以帮我们管理进程
            1.进程的创建
            2.进程的销毁
            3.任务的分配
            4.限制最大的进程数 保证系统正常运行
    池内装的东西有两种:
            装进程:进程池
            装线程:线程池
    进程池
        在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,
        并行操作可以节约大量的时间。多进程是实现并发的手段之一,需要注意的问题是:
            1 很明显需要并发执行的任务通常要远大于核数
            2 一个操作系统不可能无限开启进程,通常有几个核就开几个进程
            3 进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行)
        例如当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,
        十几个还好,但如果是上百个,上千个。。。手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
        我们就可以通过维护一个进程池来控制进程数目,比如httpd的进程模式,规定最小进程数和最大进程数...
        创建进程池的类:如果指定numprocess为3,则进程池会从无到有创建三个进程,
                    然后自始至终使用这三个进程去执行所有任务,不会开启其他进程
    使用方式?
        ThreadPoolExecutor  线程池
            实例化 时指定最大线程数
        ProcessPoolExecutor  进程池
            实例化 时指定最大进程数
        执行submit来提交任务
        from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
        p=ThreadPoolExecutor(4) # 默认开启的线程数是cpu的核数*5
        p.submit(task,i)
    总结一下:
        进程池可以自动创建进程
        进程限制最大进程数
        自动选择一个空闲的进程帮你处理任务
    进程什么时候算是空闲?
        代码执行完算是空闲
    进程池,池子内什么时候装进程:并发的任务属于计算密集型
    线程池,池子内什么时候装线程:并发的任务属于IO密集型
回调函数:
    需要回调函数的场景:进程池中任何一个任务一旦处理完了,就立即告知主进程:
        我好了额,你可以处理我的结果了。主进程则调用一个函数去处理该结果,该函数即回调函数
    我们可以把耗时间(阻塞)的任务放到进程池中,然后指定回调函数(主进程负责执行),
    这样主进程在执行回调函数时就省去了I/O的过程,直接拿到的是任务的结果。
    如果在主进程中等待进程池中所有任务都执行完毕后,再统一处理结果,则无需回调函数												
											Python-GIL 进程池 线程池的更多相关文章
- Python学习之GIL&进程池/线程池
		8.6 GIL锁** Global interpreter Lock 全局解释器锁 实际就是一把解释器级的互斥锁 In CPython, the global interpreter lock, or ... 
- Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池
		Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ... 
- 《转载》Python并发编程之线程池/进程池--concurrent.futures模块
		本文转载自Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mult ... 
- python自带的线程池和进程池
		#python自带的线程池 from multiprocessing.pool import ThreadPool #注意ThreadPool不在threading模块下 from multiproc ... 
- python并发编程-进程池线程池-协程-I/O模型-04
		目录 进程池线程池的使用***** 进程池/线程池的创建和提交回调 验证复用池子里的线程或进程 异步回调机制 通过闭包给回调函数添加额外参数(扩展) 协程*** 概念回顾(协程这里再理一下) 如何实现 ... 
- Python标准模块--concurrent.futures 进程池线程池终极用法
		concurrent.futures 这个模块是异步调用的机制concurrent.futures 提交任务都是用submitfor + submit 多个任务的提交shutdown 是等效于Pool ... 
- 并发编程-线程-死锁现象-GIL全局锁-线程池
		一堆锁 死锁现象 (重点) 死锁指的是某个资源被占用后,一直得不到释放,导致其他需要这个资源的线程进入阻塞状态. 产生死锁的情况 对同一把互斥锁加了多次 一个共享资源,要访问必须同时具备多把锁,但是这 ... 
- concurrent.futures模块(进程池/线程池)
		需要注意一下不能无限的开进程,不能无限的开线程最常用的就是开进程池,开线程池.其中回调函数非常重要回调函数其实可以作为一种编程思想,谁好了谁就去掉 只要你用并发,就会有锁的问题,但是你不能一直去自己加 ... 
- 13 并发编程-(线程)-异步调用与回调机制&进程池线程池小练习
		#提交任务的两种方式 #1.同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果,再执行下一行代码,导致程序是串行执行 一.提交任务的两种方式 1.同步调用:提交任务后,就在原地等待任务完毕,拿 ... 
随机推荐
- 描述符__get__(),__set__(),__delete__()(三十七)
			http://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__ ... 
- 使用php与mysql构建我们的网站
			技术这个玩意就是要不断的去使用,才能够熟能生巧.今天我记录的使用php与mysql构建我们的网站,其实是我两年前的时候写的项目. 现在看看自己以前写的个人项目,也会感叹时间究竟带走了什么?好记性不如烂 ... 
- 第一节,TensorFlow基本用法
			一 TensorFlow安装 TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tsnsor(张量)意味着N维数组,Flow(流)意味着基 ... 
- Java 读取文件的内容
			Java 读取文件的内容 1) CLASS_NAME: 换成自己真实的类名 2) /page/test.json: 换成自己真实的page 3) FileUtils: 来自于org.apache.co ... 
- SVN的Windows和Linux客户端操作详解
			SVN的Windows和Linux客户端操作详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Windows客户端操作 1.安装SVN客户端 a>.去官网下载svn软件 ... 
- lombok 工具类的介绍
			lombok 是一个非常非常好用的工具类.打个比方,一个bean,需要字段,get set方法 无参有参构造器,重写equals和hashcode,字段一多很麻烦.它,就是来解决这个问题的.一个注解全 ... 
- Java编程思想 学习笔记2
			二.一切都是对象 1.用引用操纵对象 在Java中,一切都被视为对象,但操纵的标识符实际上是对象的一个“引用”.可以将这想象成遥控器(引用)来操纵电视机(对象).另外,没有电视机,遥控器也可以单独存在 ... 
- 转--利用hexo搭建个人静态博客
			引用地址 可谓图文并茂,可以配合 七牛云存储(做图片等文件服务器),搭建好看的个人博客 hexo 官方指导文档 主题 官网教程 问题集锦 简书 http://blog.csdn.net/wx_9624 ... 
- MongoDB服务无法启动,windows提示发生服务特定错误:100
			MongoDB服务无法启动,windows提示发生服务特定错误:100 今天搞了下MongoDB,初上手,感觉体验不错! 但是当我想将它安装为windows 服务后,却怎么也启动不了.网上的解决办 ... 
- nginx 全局配置
			nginx 全局配置 #user nobody; # user 主模块 ,指定nginx worker 进程的运行用户组 worker_processes ; # worker_processes 开 ... 
