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)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • 用AVX2指令集优化整形数组求和

    用AVX2指令集优化整形数组求和用AVX2指令集优化高精度加法一、AVX2指令集介绍二、代码实现1.普通高精度加法2.AVX2加速高精度加法3.实现细节说明三、性能测试测试环境计时方式测试内容测试命令测试结果四、总结个人推断原因:一、AVX2指令集介绍AVX2是SIMD(单指令多数据流)指令集,支持在一个指令周期内同时对256位内存进行操作。包含乘法,加法,位运算等功能。下附Intel官网使用文档。Intel®IntrinsicsGuide我们本次要用到的指令是__m256i_mm256_add_epi8(__m2

    2022年5月7日
  • 51单片机SG90舵机控制原理

    51单片机SG90舵机控制原理舵机三根线的接法:黄线接信号线,红线接vcc,褐色线接GND舵机控制原理:通过控制PWM来控制舵机转动的角度,关于PWM的知识可以去智能小车专栏进行学习,转动周期设置为20ms,控制高电平的时间来进行舵机转动的角度。对于180°舵机t=0.5ms——————-舵机会转动0°t=1.0ms——————-舵机会转动45°t=1.5ms——————-舵机会转动90°t=2.0ms——————-舵机会转动135°t=2.5ms——————-舵机会…

    2022年6月16日
  • 从零开始学习UCOSII操作系统12–内存管理

    从零开始学习UCOSII操作系统12–内存管理从零开始学习UCOSII操作系统12–内存管理前言:在标准的C语言中,可以用malloc()和free()2个动态的分配内存和释放内存,但是在嵌入式中,调用malloc()和free()却是非常危险的。因为多次调用这两个函数,会把原来的很大的一块连续的内存区域逐渐的分割成许多非常小的而且彼此又不相邻的内存块,也就是所谓的内存碎片。这样子的话,使得程序后面连一段非常小的内存都分

    2022年5月4日
  • 信息熵和基尼系数_信息熵和基尼系数

    信息熵和基尼系数_信息熵和基尼系数一、基尼系数是什么?1)定义    下面是摘自李航《统计学习方法》中基尼系数的定义,非常清晰。2)基尼系数有什么意义?    我们可以先来看一组数据X的取值 方案一 方案二 方案三 方案四 P的平方 方案一 方案二 方案三 方案四类别一 0.9 0.5 0.4 0.2 p1^2 0.81 0.25 0.16 0.04类别二 0.1 0.5 0.3 0.2 p2^2 0.01 0.25 0.09 0…

    2022年10月10日
  • 最常见的24个逻辑错误_数学主要错误分析原因

    最常见的24个逻辑错误_数学主要错误分析原因前言:最近使用阿里云windows2008R2云服务器搭建网站QQ互联接入(第三方登录)服务的过程中,使用了phpcmsV9提供的V9.6.3压缩包内的.htaccess文件。几经辗转,仍然没能解决过程中遇到的问题,问了一些技术大咖,有人说可能是500错误。以前知道有400报错,还真不知道有个500错误,所以上网查询之后,觉得应该小结一篇。1.造成500错误常见原因有:ASP语法出…

    2022年4月20日
  • bwapp之sql注入_sql注入语句入门

    bwapp之sql注入_sql注入语句入门步骤下面简要介绍手工注入(非盲注)的步骤。1.判断是否存在注入,注入是字符型还是整数型2.猜解SQL查询语句中的字段数(orderby)3.确定显示的字段顺序4.获取当前数据库(爆库)5.获取数据库中的表(爆表)6.获取表中的字段名(爆字段)7.下载数据(爆数据)0x01SQLInjection(GET/Search)…

    2022年9月23日

发表回复

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

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