zoukankan      html  css  js  c++  java
  • Python多线程编程

    学习还是要多总结,不然老忘啊。
    经常说的一个话题:Python多线程是假的多线程。具体python为什么在多线程方面比较弱呢?

    以下资料来自于网络的整理。

    全局解释器锁(GIL)

    Python代码的执行由Python虚拟机(解释器)来控制。

    Python在设计之初就考虑要在主循环中,同时只有一个线程在执行,就像单CPU的系统中运行多个进程那样,内存中可以存放多个程序,但任意时刻,只有一个程序在CPU中运行。

    同样地,虽然Python解释器可以运行多个线程,只有一个线程在解释器中运行。

    对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同时只有一个线程在运行。在多线程环境中,Python虚拟机按照以下方式执行。

    1. 设置GIL。
    2. 切换到一个线程去执行。
    3. 运行。
    4. 把线程设置为睡眠状态。
    5. 解锁GIL。
    6. 再次重复以上步骤。

    对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。如果某线程并未使用很多I/O操作,它会在自己的时间片内一直占用处理器和GIL。也就是说,I/O密集型的Python程序比计算密集型的Python程序更能充分利用多线程的好处。

    我们都知道,比方我有一个4核的CPU,那么这样一来,在单位时间内每个核只能跑一个线程,然后时间片轮转切换。但是Python不一样,它不管你有几个核,单位时间多个核只能跑一个线程,然后时间片轮转。看起来很不可思议?但是这就是GIL搞的鬼。任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。

    即:

    • 你就不应该用Python写CPU密集型的代码…效率摆在那里…

    如果确实需要在CPU密集型的代码里用concurrent,就去用multiprocessing库。这个库是基于multi process实现了类multi thread的API接口,并且用pickle部分地实现了变量共享。

    再加一条,如果你不知道你的代码到底算CPU密集型还是IO密集型,教你个方法:multiprocessing这个module有一个dummy的sub module,它是基于multithread实现了multiprocessing的API。假设你使用的是multiprocessing的Pool,是使用多进程实现了concurrency

    from multiprocessing import Pool
    

    如果把这个代码改成下面这样,就变成多线程实现concurrency

    from multiprocessing.dummy import Pool
    

    两种方式都跑一下,哪个速度快用哪个就行了。

    此外,还有concurrent.futures这个东西,包含ThreadPoolExecutor和ProcessPoolExecutor,可能比multiprocessing更简单

    concurrent.futures

    concurrent.futures基础:
    python并发之concurrent.futures https://blog.csdn.net/dutsoft/article/details/54728706

    concurrent.futures实例:
    python concurrent.futures https://www.cnblogs.com/kangoroo/p/7628092.html

    用c语言链接库来解决cpu密集型任务的多核多线程问题

    难道就如此?我们没有办法在Python中利用多核?当然可以!刚才的多进程算是一种解决方案,还有一种就是调用C语言的链接库。对所有面向I/O的(会调用内建的操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。我们可以把一些 计算密集型任务用C语言编写,然后把.so链接库内容加载到Python中,因为执行C代码,GIL锁会释放,这样一来,就可以做到每个核都跑一个线程的目的!

    总结

    Python多线程相当于单核多线程,多线程有两个好处:CPU并行,IO并行,单核多线程相当于自断一臂。所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

    参考

    https://www.zhihu.com/question/23474039/answer/269526476

  • 相关阅读:
    js 数组详解(javascript array)
    CentOS 修改IP地址, DNS, 网关
    Leetcode 652.寻找重复的子树
    Leetcode 650.只有两个键的键盘
    Leetcode 649.Dota2参议院
    Leetcode 648.单词替换
    Leetcode 647.回文子串
    Leetcode 645.最长数对链
    Leetcode 643.子数组最大平均数I
    Leetcode 640.求解方程
  • 原文地址:https://www.cnblogs.com/toone/p/8856910.html
Copyright © 2011-2022 走看看