Python中多线程与多进程的恩恩怨怨
概念:
并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。
并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
最近在看Python的多线程,经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢?
要知其然,更要知其所以然。所以有了下面的深入研究:
首先强调背景:
1. GIL是什么?
GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。
2. 每个CPU在同一时间只能执行一个线程
在单核CPU下的多线程其实都只是并发,不是并行,并发和并行从宏观上来讲都是同时处理多路请求的概念。但并发和并行又有区别,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。
在Python多线程下,每个线程的执行方式:
获取GIL
执行代码直到sleep或者是python虚拟机将其挂起。
释放GIL
可见,某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。
在Python2.x里,GIL的释放逻辑是当前线程遇见IO操作或者ticks计数达到100(ticks可以看作是Python自身的一个计数器,专门作用于GIL,每次释放后归零,这个计数可以通过 sys.setcheckinterval 来调整),进行释放。
而每次释放GIL锁,线程进行锁竞争、切换线程,会消耗资源。并且由于GIL锁存在,python里一个进程永远只能同时执行一个线程(拿到GIL的线程才能执行),这就是为什么在多核CPU上,python的多线程效率并不高。
那么是不是python的多线程就完全没用了呢?
在这里我们进行分类讨论:
CPU密集型代码(各种循环处理、计数等等),在这种情况下,由于计算工作多,ticks计数很快就会达到阈值,然后触发GIL的释放与再竞争(多个线程来回切换当然是需要消耗资源的),所以python下的多线程对CPU密集型代码并不友好。
IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率)。所以python的多线程对IO密集型代码比较友好。(下方有爬虫示例)
而在python3.x中,GIL不使用ticks计数,改为使用计时器(执行时间达到阈值后,当前线程释放GIL),这样对CPU密集型程序更加友好,但依然没有解决GIL导致的同一时间只能执行一个线程的问题,所以效率依然不尽如人意。
请注意:多核多线程比单核多线程更差,原因是单核下的多线程,每次释放GIL,唤醒的那个线程都能获取到GIL锁,所以能够无缝执行,但多核下,CPU0释放GIL后,其他CPU上的线程都会进行竞争,但GIL可能会马上又被CPU0拿到,导致其他几个CPU上被唤醒后的线程会醒着等待到切换时间后又进入待调度状态,这样会造成线程颠簸(thrashing),导致效率更低。
回到最开始的问题:经常我们会听到老手说:“python下想要充分利用多核CPU,就用多进程”,原因是什么呢?
原因是:每个进程有各自独立的GIL,互不干扰,这样就可以真正意义上的并行执行,所以在python中,多进程的执行效率优于多线程(仅仅针对多核CPU而言)。
所以在这里说结论:多核下,想做并行提升效率,比较通用的方法是使用多进程,能够有效提高执行效率
爬虫示例比较、下图是在双核CPU机器上执行单线程爬虫、多线程并发、多进程并行、所使用的时间与CPU使用率对比
单线程:
多线程并发执行:(线程池)
多进程并行执行:(进程池)
单线程VS多线程:在爬虫运行遇到IO阻塞时,多线程会切换到另外一条线程执行,某时刻该线程IO顺通并获得GIL锁后继续执行,CPU利用率高;单线程会等待阻塞,CPU利用率低;多线程比单线程快。
多线程VS多进程:多线程存在GIL锁,同一时刻只能有一条线程执行;在多进程中,每一个进程都有独立的GIL,不会发生GIL冲突;但在这个例子中,爬虫属于IO密集型,多进程适用于CPU计算密集型,所以用时较长,速度慢于多线程并发。
多线程、多进程VS单线程: 单线程惨败
Python中多线程与多进程的恩恩怨怨的更多相关文章
- python中多线程,多进程,队列笔记(一)
threading简介:If you want your application to make better use of the computational resources of multi- ...
- python中多线程,多进程,多协程概念及编程上的应用
1, 多线程 线程是进程的一个实体,是CPU进行调度的最小单位,他是比进程更小能独立运行的基本单位. 线程基本不拥有系统资源,只占用一点运行中的资源(如程序计数器,一组寄存器和栈),但是它可以与同属于 ...
- Python之多线程和多进程
一.多线程 1.顺序执行单个线程,注意要顺序执行的话,需要用join. #coding=utf-8 from threading import Thread import time def my_co ...
- 通过编写聊天程序来熟悉python中多线程及socket的用法
1.引言 Python中提供了丰富的开源库,方便开发者快速就搭建好自己所需要的应用程序.本文通过编写基于tcp/ip协议的通信程序来熟悉python中socket以及多线程的使用. 2.python中 ...
- Python 中多线程之 _thread
_thread模块是python 中多线程操作的一种模块方式,主要的原理是派生出多线程,然后给线程加锁,当线程结束的 时候取消锁,然后执行主程序 thread 模块和锁对象的说明 start_new_ ...
- 为什么在python中推荐使用多进程而不是多线程(转载)
最近在看Python的多线程,经常我们会听到老手说:"Python下多线程是鸡肋,推荐使用多进程!",但是为什么这么说呢? 要知其然,更要知其所以然.所以有了下面的深入研究: GI ...
- Python的多线程和多进程
(1)多线程的产生并不是因为发明了多核CPU甚至现在有多个CPU+多核的硬件,也不是因为多线程CPU运行效率比单线程高.单从CPU的运行效率上考虑,单任务进程及单线程效率是最高的,因为CPU没有任何进 ...
- Python【多线程与多进程】
import time,threading print("=======串行方式.并行两种方式调用run()函数=======")def run(): print('哈哈哈') # ...
- python中多线程
多线程 什么是多线程 开启线程的两种方式 进程和线程的区别 Thread对象的其他属性和方法 守护线程 死锁现象与递归锁 信号量.Event定时器 线程Queue 进程池和线程池 什么是多线程 在传统 ...
随机推荐
- git学习记录——基础概念和文件的基本操作
夸一下git git是当前世界上最先进的分布式版本控制系统 优势: 1.不必联网 2.Git极其强大的分支管理,把SVN等远远抛在了后面. 集中式的代表CVS和SVN 分布式的代表BitKeeper, ...
- loading遮罩
.loading{ position: relative; cursor: default; point-events: none; text-shadow: none!important; colo ...
- spring cloud深入学习(六)-----熔断监控Hystrix Dashboard和Turbine
Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数 ...
- tumblr arch information
http://developer.51cto.com/art/201305/395757.htm 每月超过30%的增长当然不可能没有挑战,其中可靠性问题尤为艰巨.每天5亿次浏览量,峰值每秒4万次请求, ...
- 学习Python笔记---if 语句
条件测试 每条if语句的核心都是一个值为True或False的表达式,这种表达式被称为条件测试.Python根据条件测试的值True还是False来决定是否执行if语句中的代码.如果条件测试的值为Tr ...
- mysql连接出现Unknown system variable 'tx_isolation'异常
出现这个异常,是因为mysql-connector-java.jar的版本太低,数据库的版本太高,不匹配导致的. 因此将mysql-connector-java升级到最新版本就解决了问题. 最新的三个 ...
- (转)Sql server中 如何用sql语句创建视图
1.视图的作用 视图的作用: 第一点:使用视图,可以定制用户数据,聚焦特定的数据. 解释: 在实际过程中,公司有不同角色的工作人员,我们以销售公司为例的话, 采购人员,可以需要一些与其 ...
- 如何让div处于body居中的状态
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8&qu ...
- cmd 运行 python
①cmd 进入行命令: ②输入 “python” + “空格”,即 ”python “:将已经写好的脚本文件拖拽到当前光标位置,然后敲回车运行即可.
- sql server 创建视图添加表时出现从其他数据库导入的表未显示出来
创建视图添加表时出现从其他数据库导入的表未显示出来,通过数据库刷新,也不能解决.关闭SQL server management studio 后,再次进入,在创建视图的时候添加表的列表就出现了新导入的 ...