作家
登录

深入理解GIL:如何写出高性能及线程安全的Python代码

作者: 来源: 2017-05-26 11:06:13 阅读 我要评论

  •  
  •     t = threading.Thread(target=do_connect) 
  •  
  •     t.start()  
  • 两个线程在同一时刻只能有一个履行 Python ,但一旦线程开端连接,它就会放弃 GIL ,如许其他线程就可以运行。这意味着两个线程可以并发等待套接字连接,这是一件功德。在同样的时光内它们可以做更多的工作。

    让我们打开盒子,看看一个线程在连接建立时实际是若何放弃 GIL 的,在 socketmodule.c 中:

    1. /* s.connect((host, port)) method */ 
    2.  
    3. static PyObject * 
    4.  
    5. sock_connect(PySocketSockObject *s, PyObject *addro) 
    6.  
    7.  
    8.     sock_addr_t addrbuf; 
    9.  
    10.     int addrlen; 
    11.  
    12.     int res; 
    13.  
    14.   
    15.  
    16.     /* convert (host, port) tuple to C address */ 
    17.  
    18.     getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen); 
    19.  
    20.   
    21.  
    22.     Py_BEGIN_ALLOW_THREADS 
    23.  
    24.     res = connect(s->sock_fd, addr, addrlen); 
    25.  
    26.     Py_END_ALLOW_THREADS 
    27.  
    28.   
    29.  
    30.     /* error handling and so on .... */ 
    31.  
    32.  

    线程恰是在Py_BEGIN_ALLOW_THREADS 宏处放弃 GIL;它被简单定义为:

    当然 Py_END_ALLOW_THREADS 从新获取锁。一个线程可能会在这个地位堵塞,等待另一个线忱矸⑴锁;一旦这种情况产生,等待的线程会掠夺回锁,并恢复履行你的Python代码。简而言之:当N个线程在收集 I/O 堵塞,或等待从新获取GIL,而一个线程运行Python。

    下面来看一个应用协同式多义务处理快速抓取很多 URL 的完全例子。但在此之前,先比较下协同式多义务处理和其他情势的多义务处理。

    抢占式多义务处理

    Python线程可以主动释放 GIL,也可以先发制人抓取 GIL 。

    让我们回想下 Python 是若何运行的。你的法度榜样分两个阶段运行。起首,Python文本被编译成一个名为字节码的简单二进制格局。第二,Python说冥器的主回路,一个名叫 pyeval_evalframeex() 的函数,流畅地攫取字节码,逐个履行个中的指令。

    当说冥器经由过程字节码时,它会按期放弃GIL,而不须要经由正在履行代码的线程许可,如许其他线程便能运行:

    (Jython 和 IronPython 供给单过程的并行,但它们远没有充分实现 CPython 的兼容性。有软件事务内存的 PyPy 有朝一日可以运行更快。如不雅你对此好奇,尝尝这些说冥器。)

    默认情况下,检测距离是1000 字节码。所有线程都运行雷同的代码,并以雷同的方法按期大年夜他们的锁中抽出。在 Python 3 GIL 的实施加倍复杂,检测距离不是一个固定命目标字节码,而是15 毫秒。然而,对于你的代码,这些差别并不明显。

    将多个线状物编织在一路,须要技能。

    如不雅一个线程可以随时掉去 GIL,你必须使让代码线程安然。 然而 Python 法度榜样员对线程安然的看法大年夜不合于 C 或者 Java 法度榜样员,因为很多 Python 操作是原子的。

    在列表中调用 sort(),就是原子操作的例子。线程不克不及在排序时代被打断,其他线程大年夜来看不到列表排序的部分,也不会在列表排序之前看到过时的数据。原子操作简化了我们的生活,但也有不测。例如,+ = 似乎比 sort() 函数简单,但+ =不是原子操作。你怎么知道哪些操作是原子的,哪些不是?

    看看这个代码:

    1. n = 0 

        推荐阅读

        公有云账单:忽略这四项成本,后果很严重!

      中断产生,并由中断导致的宕机,将导致云用户的收入受损。这些故障也可能对企业的荣誉产生晦气影响,即使问题已经解决了几个礼拜或几个月。比拟于本地基本架构,公有云计算平日会削减企业>>>详细阅读


      本文标题:深入理解GIL:如何写出高性能及线程安全的Python代码

      地址:http://www.17bianji.com/lsqh/35440.html

    关键词: 探索发现

    乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

    网友点评
    自媒体专栏

    评论

    热度

    精彩导读
    栏目ID=71的表不存在(操作类型=0)