zoukankan      html  css  js  c++  java
  • Python多线程补充—GIL

    GIL(Global Interpreter Lock )

    GIL从名称翻译:全局解释器锁。

    作用:限制同一个进程内只同一时刻允许一个线程执行(不允许并行),即使计算机有多核功能。从而保证线程安全

    来源:Cpython解释器

    也就是说GIL是一把互斥锁,限制程序并行执行。它的级别是解释器级别的,强制的,不是Python的特性,而是Cpython解释器特有的。

    为什么会有GIL呢,查过一些资料,我的理解是从python垃圾回收机制说起

    垃圾回收机制

    Python中的垃圾回收是以引用计数为主,分代收集为辅。
    在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。

    1. 导致引用计数+1的情况
      1. 对象被创建,例如a=23
      2. 对象被引用,例如b=a
      3. 对象被作为参数,传入到一个函数中,例如func(a)
      4. 对象作为一个元素,存储在容器中,例如list1=[a,a]
    2. 导致引用计数-1的情况
      1. 对象的别名被显式销毁,例如del a
      2. 对象的别名被赋予新的对象,例如a=24
      3. 一个对象离开它的作用域,例如f函数执行完毕时,func函数中的局部变量(全局变量不会)
      4. 对象所在的容器被销毁,或从容器中删除对象

             (注:摘自:http://www.cnblogs.com/Xjng/p/5128269.html

    如果,一个变量同时被引用呢,在同一个进程内,各个线程可以共享数据。当他们同时引用一个对象,则会使垃圾回收机制的计数错误,可能使对象还有引用,但是却被回收了。因此Cpython解释器就引入了GIL锁

    在一个进程内,每个线程想要获取cpu运行的权限,都要获取GIL锁对象,因此线程们无法并行执行。也就避免了上述问题。

    而获取GIL的线程,无论何时,它一旦睡眠或者是等待I/O,它没有了运行PYthon代码的必要,它就会让出GIL,其他线程就会有获取GIL的机会。这也叫做协同式多任务管理

    既然有了GIL,为什么还需要自己给数据加上锁(Lock)呢?

      因为除了协同式多任务管理,还有抢占式多任务管理,也就是说一个线程在执行Python代码时,有可能会被强制让出GIL,让其他线程执行。

      而且在数据处理的过程中也能会有I/O阻塞,使线程主动让出GIL,其他线程可能获取GIL处理同一个数据,造成数据混乱

    所以,GIL保护的是解释器级别的数据,我们自己创建的数据需要我们自己加锁。

    线程的互斥锁可见:https://www.cnblogs.com/ifyoushuai/p/9471569.html

    总结:

      GIL的优点就是保护线程安全,缺点也很明显:无法利用多核优势,使程序运行速度变慢,而现在计算机多核是十分普遍,似乎GIL的缺陷也显得更加的明显,但是Pyhton中很多库都是默认有GIL存在的,而且上述也提到,遇到I/O阻塞会切换,无论多核单核,也无法改变阻塞的时间。因此GIL对于 I/O密集型的任务,影响不大。对于计算密集型的任务,就用多进程并发吧。

  • 相关阅读:
    Zstack中任务,事件,消息之间的关系
    Zigbee折腾之旅:(一)CC2530最小系统
    计算机中原码,反码,补码之间的关系
    Python3
    Python3
    Python3
    【基础】强软弱虚引用
    SpringBoot上传文件时MultipartFile报空问题解决方法
    Mockito中的@Mock和@Spy如何使用
    Vim 多行剪切、复制和删除
  • 原文地址:https://www.cnblogs.com/ifyoushuai/p/9481340.html
Copyright © 2011-2022 走看看