python究竟要不要使用多线程

(1)python多线程究竟有没有用?(2)python虚拟机机制如何控制代码的执行?(3)python中多进程处理原理是怎么样的?1.先来看两个例子(1)例1分别用单线程、使用多线程、使

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

在总结concurrent.futures库之前先来弄明白三个问题:   

(1)python多线程究竟有没有用?

(2)python虚拟机机制如何控制代码的执行?

(3)python中多进程处理原理是怎么样的?

1. 先来看两个例子

(1)例1

  分别用单线程、使用多线程、使用多进程三种方法对最大公约数进行计算

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time
  def gcd(pair):

    a, b = pair

    low = min(a, b)

    for i in range(low, 0, -1):

        if a % i == 0 and b % i == 0:

            return i

 numbers = [

    (1963309, 2265973), (1879675, 2493670), (2030677, 3814172),

    (1551645, 2229620), (1988912, 4736670), (2198964, 7876293)
if __name__ == '__main__':
    # 不使用多线程和多进程
    start = time.time()
    results = list(map(gcd,numbers))
    end = time.time()
    print('未使用--timestamp:{:.3f} second'.format(end-start))

    #使用多线程
    start = time.time()
    pool = ThreadPoolExecutor(max_workers=3)
    results = list(pool.map(gcd,numbers))
    end = time.time()
    print('使用多线程--timestamp:{:.3f} second'.format(end-start))

    #使用多进程
    start = time.time()
    pool = ProcessPoolExecutor(max_workers=3)
    results = list(pool.map(gcd,numbers))
    end = time.time()
    print('使用多进程程--timestamp:{:.3f} second'.format(end-start))

  输出:

  python究竟要不要使用多线程

  之前线程数和进程说都为3,现在修改为4再测试

  python究竟要不要使用多线程

  为了更能说明问题,将线程数和进程说继续增加为5

  python究竟要不要使用多线程

  至于区别,大家自己感受,测试的条件(计算过于简单)、测试的环境都会影响测试结果

(2)例2

  同样分别用单线程、使用多线程、使用多进程三种方法对网页进行爬虫,只是简单的返回status_code

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time 
import requests

def download(url):
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0',
                'Connection':'keep-alive',
                'Host':'example.webscraping.com'}
    response = requests.get(url, headers=headers)
    return(response.status_code)
    
if __name__ == '__main__':
    urllist = ['http://example.webscraping.com/places/default/view/Afghanistan-1',
               'http://example.webscraping.com/places/default/view/Aland-Islands-2',
               'http://example.webscraping.com/places/default/view/Albania-3',
               'http://example.webscraping.com/places/default/view/Algeria-4',
               'http://example.webscraping.com/places/default/view/American-Samoa-5']
               
    start = time.time()           
    result = list(map(download, urllist))
    end = time.time()
    print('status_code:',result)
    print('未使用--timestamp:{:.3f}'.format(end-start))
    
    pool = ThreadPoolExecutor(max_workers = 3)
    start = time.time()           
    result = list(pool.map(download, urllist))
    end = time.time()
    print('status_code:',result)
    print('使用多线程--timestamp:{:.3f}'.format(end-start))
    
    pool = ProcessPoolExecutor(max_workers = 3)
    start = time.time()           
    result = list(pool.map(download, urllist))
    end = time.time()
    print('status_code:',result)
    print('使用多进程程--timestamp:{:.3f}'.format(end-start))

   输出:

  python究竟要不要使用多线程

  一下就看出了区别

2. python虚拟机机制如何控制代码执行?

  对于python来说,作为解释型语言,Python的解释器必须做到既安全又高效。我们都知道多线程编程会遇到的问题,解释器要留意的是避免在不同的线程操作内部共享的数据,同时它还要保证在管理用户线程时保证总是有最大化的计算资源。python是通过使用全局解释器锁来保护数据的安全性。

  python 代码的执行由python虚拟机来控制,即Python先把代码(.py文件)编译成字节码(字节码在Python虚拟机程序里对应的是 PyCodeObject对象,.pyc文件是字节码在磁盘上的表现形式),交给字节码虚拟机,然后虚拟机一条一条执行字节码指令,从而完成程序的执行。 python在设计的时候在虚拟机中,同时只能有一个线程执行。同样地,虽然python解释器中可以运行多个线程,但在任意时刻,只有一个线程在解释器 中运行。而对python虚拟机的访问由全局解释器锁来控制,正是这个锁能保证同一时刻只有一个线程在运行。

  在多线程的环境中,python虚拟机按一下 方式执行:

  (1)设置GIL(global interpreter lock)

  (2)切换到一个线程执行

  (3)运行:指定数量的字节码指令、线程主动让出控制(可以调用time.sleep(0))

  (4)把线程设置为睡眠状态

  (5)解锁GIL

  (6)再次重复以上步骤。

  GIL的特性,也就导致了python不能充分利用多核cpu。而 对面向I/O的(会调用内建操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。如果线程 并未使用很多I/O操作,它会在自己的时间片一直占用处理器和GIL。

3. python多线程究竟有没有用?

  通过前面的例子和python虚拟机制的理解对多线程的使用应该很清楚了,I/O密集型python程序比计算密集型的程序更能充分利用多线 程的好处。 总之,在计算密集型的程序中不要python多线程,使用python多进程进行并发编程,就不会有GIL这种问题存在,并且也能充分利用多核cpu。

  (1)GIL不是bug,Guido也不是水平有限才留下这么个东西。龟叔曾经说过,尝试不用GIL而用其他的方式来做线程安全,结果python语言整体效率又下降了一倍,权衡利弊,GIL是最好的选择——不是去不掉,而是故意留着的

  (2)想让python计算速度快起来,又不想写C,用pypy吧,这才是真正的大杀器

  (3)可以使用协程来提高cpu的利用率,使用multiprocessing和gevent

4. python多进程执行原理  

  ProcessPoolExecutor类会利用multiprocessing模块所提供的底层机制,以例2作为例子描述下多进程执行流程:

  (1)把urllist列表中的每一项输入数据都传给map

  (2)用pickle模块对数据进行序列化,将其变成二进制形式

  (3)通过本地套接字,将序列化之后的数据从解释器所在的进程发送到子解释器所在的进程

  (4)在子进程中,用pickle对二进制数据进行反序列化,将其还原成python对象

  (5)引入包含download函数的python模块

  (6)各个子进程并行的对各自的输入数据进行计算

  (7)对运行的结果进行序列化操作,将其转变成字节

  (8)将这些字节通过socket复制到主进程之中

  (9)主进程对这些字节执行反序列化操作,将其还原成python对象

  (10)最后把每个子进程所求出的计算结果合并到一份列表之中,并返回给调用者。

  multiprocessing开销比较大,原因就在于:主进程和子进程之间通信,必须进行序列化和反序列化的操作

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120046.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • phpstom 2022.01 激活码【最新永久激活】2022.02.03

    (phpstom 2022.01 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年4月1日
    43
  • C语言位运算符详解「建议收藏」

    C语言位运算符详解「建议收藏」目录位运算符简介1、按位与位运算符简介C语言既具有高级语言的特点,又具有低级语言的特性,如支持位运算就是其具体体现。这是因为,C语言1、按位与

    2022年10月5日
    0
  • TB6612FNG 驱动学习笔记

    TB6612FNG是东芝半导体公司生产的一款直流电机驱动器件,它具有大电流MOSFET-H桥结构,双通道电路输出,可同时驱动2个电机。TB6612FNG每通道输出最高1.2A的连续驱动电流,启动峰值电流达2A/3.2A(连续脉冲/单脉冲);4种电机控制模式:正转/反转/制动/停止;PWM支持频率高达100kHz;待机状态;片内低压检测电路与热停机保护电路;工作温度:-20~85℃;SSOP…

    2022年4月7日
    59
  • DOS 和 Linux 常用命令的对比

    DOS和Linux常用命令的对比许多在shell提示下键入的Linux命令都与你在DOS下键入的命令相似。事实上,某些命令完全相同。本附录提供了Windows的DOS提示

    2021年12月26日
    39
  • ov7725摄像头人脸识别_监控摄像头图像倒置怎么办

    ov7725摄像头人脸识别_监控摄像头图像倒置怎么办前言:摄像头的工作原理大致为:景物通过镜头(LENS)生成的光学图像投射到图像传感器表面上,然后转为电信号,经过A/D[1](模数转换)转换后变为数字图像信号,再送到数字信号处理芯片(DSP)中加工处理,再传输给其他显示硬件就可以显示看到图像了我要讲解的是0V7725摄像头,带FIFO缓存,以及通过STM32F103MCU进行控制,在采用ILI9341控制器芯片的液晶屏(分辨率240*32

    2022年9月15日
    0
  • python灰度图生成g代码_artcam pro 通过灰度图生成G代码详细图文教程

    python灰度图生成g代码_artcam pro 通过灰度图生成G代码详细图文教程本文是使用artcampro把灰度图转成G代码,看到喜欢的雕刻,可以自己先做成灰度图,然后转换成G代码,今天特地做了一个教程,仅供刚刚接触者使用!新手可以看看,老手请高抬贵手,不要嘲笑。自己技术有限,将就看吧!希望对大家有用!灰度图生成G代码详细图文教程如下:1、先找一张灰度图:2、打开软件,点“文件”–“新的”–“通过图像文件”,找到刚才自己打开的灰度图,双击图片就可以了。3、设置雕刻尺…

    2022年6月20日
    46

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号