python究竟要不要使用多线程
在总结concurrent.futures库之前先来弄明白三个问题:
(1)python多线程究竟有没有用?
(2)python虚拟机机制如何控制代码的执行?
(3)python中多进程处理原理是怎么样的?
1. 先来看两个例子
(1)例1
分别用单线程、使用多线程、使用多进程三种方法对最大公约数进行计算
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time
a, b = pair
low = min(a, b)
for i in range(low, 0, -1):
if a % i == 0 and b % i == 0:
return i
(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=)
results = list(pool.map(gcd,numbers))
end = time.time()
print('使用多线程--timestamp:{:.3f} second'.format(end-start)) #使用多进程
start = time.time()
pool = ProcessPoolExecutor(max_workers=)
results = list(pool.map(gcd,numbers))
end = time.time()
print('使用多进程程--timestamp:{:.3f} second'.format(end-start))
输出:

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

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

至于区别,大家自己感受,测试的条件(计算过于简单)、测试的环境都会影响测试结果
(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 = )
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 = )
start = time.time()
result = list(pool.map(download, urllist))
end = time.time()
print('status_code:',result)
print('使用多进程程--timestamp:{:.3f}'.format(end-start))
输出:

一下就看出了区别
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开销比较大,原因就在于:主进程和子进程之间通信,必须进行序列化和反序列化的操作
python究竟要不要使用多线程的更多相关文章
- Python并发编程系列之多线程
1 引言 上一篇博文详细总结了Python进程的用法,这一篇博文来所以说Python中线程的用法.实际上,程序的运行都是以线程为基本单位的,每一个进程中都至少有一个线程(主线程),线程又可以创建子线程 ...
- 聊聊Python中的多进程和多线程
今天,想谈一下Python中的进程和线程. 最近在学习Django的时候,涉及到了多进程和多线程的知识点,所以想着一下把Python中的这块知识进行总结,所以系统地学习了一遍,将知识梳理如下. 1. ...
- Python爬虫进阶五之多线程的用法
前言 我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread ...
- python第九周:paramiko多线程、队列
1.paramiko模块 用处:连接远程服务器并执行相关操作 使用方法: SSHClient:连接远程服务器并执行基本命令 import paramiko #创建SSH对象 ssh = paramik ...
- Python+Unittest+Requests+PyMysql+HTMLReport 多线程并发接口化框架
整体框架使用的是:Python+Unittest+Requests+PyMysql+HTMLReport 多线程并发模式 主要依赖模块 Unittest.Requests.PyMysql.HTMLRe ...
- 深入浅析python中的多进程、多线程、协程
深入浅析python中的多进程.多线程.协程 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源 ...
- python进阶(9)多线程
什么是线程? 线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位.线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其 ...
- Python进阶——为什么GIL让多线程变得如此鸡肋?
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 做 Python 开发时,想必你肯定听过 GIL,它经常被 Python 程序员吐槽,说 Pytho ...
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
随机推荐
- 如何修改Eclipse中的快捷键
首先打开Eclipse,Windows->Preferences ↓ 进入Preferences界面后,选择General->Keys ↓ 接下来你就会看到: 接下来点击OK就可以生效了.
- java 断言工具类
1.断言工具类 package com.sze.redis.util; import java.util.Collection; import java.util.Map; import com.sz ...
- 【HackerRank】 Game Of Thrones - I
King Robert has 7 kingdoms under his rule. He gets to know from a raven that the Dothraki are going ...
- requestAnimationFrame 的实验性实践
记得当 requestAnimationFrame 出现时我立马就石更了,就跟初次玩耍 transition 时一样,欣喜若狂... 然后,然后特么的就懵逼了,这明明就是口挖不通的深井呀(如果是我傻, ...
- Android 平台电容式触摸屏的驱动基本原理
Android 平台电容式触摸屏的驱动基本原理 Android 平台电容式触摸屏硬件基本原理 Linux 与 Android 的多点触摸协议 Linux输入子系统:事件的编码
- console、JSON兼容问题
console在ie8上面竟然有兼容问题,JSON.stringify()在ie10下竟然会报错,再页面上引用一个json2.js能解决此问题.
- Windows 2012 系统汉化
远程登录服务器 控制面板,选择“语言” (Windows 2012 自带的语言包 ) 此处需要等待 安装完成,选择中文 重启后 应该就不需要做其他的操作了
- Python安装setuptools时报Compression requires the (missing) zlib
装机员为您提供Python安装setuptools时报Compression requires the (missing) zlib的文章咨询供您阅读,如何使用Python安装setuptools时报 ...
- maven 中pom.xml文件依赖包从本地加载如何配置?
比如我现在有一个需求是:项目中要加载ueditor的jar架构包,并且用maven构建的项目 那么在pom.xml文件中如配置: 说明:${project.basedir} 是maven 自带(内置) ...
- spark学习3(sqoop1.4.6安装)
sqoop目前有两个版本sqoop1和sqoop2,这里安装的是sqoop1版本 1)将软件上传到spark1节点 2)修改权限 [root@spark1 sqoop]# chmod u+x sqoo ...