GIL全局解释器
'
GIL是一个互斥锁:保证数据的安全(以牺牲效率来换取数据的安全)
阻止同一个进程内多个线程同时执行(不能并行但是能够实现并发)
并发:看起来像同时进行的
GIL全局解释器存在的原因是因为CPython解释器的内存管理不是线程安全的
垃圾回收机制
1 引用计数
2 标记清楚
3 分代回收
同一个进程下的多个线程不能实现并行 但是能够实现并发 多个进程下的线程能够实现并行
'
在一个python的进程内,不仅只有主线程或者还有该主线程开启的其他线程,海有解释器开启的垃圾回收等解释器级别的线程,总之所有的线程都运行在这一个进程内。
1 所有数据都是共享的,这其中,代码作为一种数据也是被所有线程共享的(test.py的所有代码以及CPython解释器的所有
代码) 例如:test.py定义一个函数work,在进程内所有线程都能访问到work的代码,于是我们可以开启三个线程然后target都指
向该代码,能访问到意味着就是可以执行。 2 所有线程的任务,都需要将任务的代码当做参数传给解释器的代码去执行,即所有的线程想要运行自己的任务,首先需要解
决的是能够访问到解释器的代码。
综上:
如果多个线程的target=work,那么执行流程是多个线程先访问到解释器的代码,即拿到执行权限,然后将target的代码交给解释器的代码去执行解释器的代码是所有线程共享的,所以垃圾回收线程也可能放到解释器的代码而执行,这就导致了一个问题:对于同一个数据100 ,可能是线程1执行x=100的同时,而垃圾回收执行的是回收100的操作,解决这种问题就是解锁,保证python解释器同一时间只能执行一个任务的代码。
GIL全局解释锁是所有解释型语言的通病!
GIL全局解释锁是python的问题吗?
它是CPython解释器的特点
GIL与多线程
有了GIL的存在,同一时刻同一进程中只有一个线程被执行
进程可以利用多核,但是开销大,而python的多线程开销小,但却无法利用多核优势?
要解决这个问题,先统一一个条件:
1 cpu到底是用来做计算的,还是用来最I/O的? 2 多cpu,意味着可以由多个核并行完成计算,所以多核提升的计算机性能 3 每一个cpu一旦遇到I/O阻塞,任然需要等待,所以多核对I/O操作没什么用处
一个工人相当于cpu,此时计算相当于工人在干活,I/O阻塞相当于为工人干活提供所需原材料的过程,工人干活的过程中如果没有原料了,则工人干活的过程需要停止,直到等待原材料的带来。
如果你的工厂干的大多数任务都需要准备原材料的过程(I/O密集型),那么你有再多的工人,意义也不打,还不如一个人,在等材料的过程中让工人去干别的活,
反过来讲,如果你的工厂原材料都齐全,那当然是工人越多,效率越高
结论:
对计算来说,cpu越多越好,但是对于I/O来说,在多的cpu也没用
当然对于运行一个程序来说,随着cpu的增多执行效率肯定会有所提高(不管提高幅度多大,总会有所提高),这是因为一个程序基本上不会是纯计算或者纯I/O,所以我们只能相对的去看一个程序到底计算密集型还是I/O密集型,从而进一步分析python的多线程到底有无用处。
我们有四个人物需要处理,处理方式肯定是要玩出并发的效果,解决方案可以是:
方案一:开启四个进程
方案二:一个进程下,开启四个线程 单核情况下,分析结果:
如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜
如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜 多核情况下,分析结果:
如果四个任务是计算密集型,多核意味着并行计算,在python中一个进程中同一时刻只有一个线程执行用不上多核,方案一胜
如果四个任务是I/O密集型,再多的和也解决不了I/O问题,方案二胜 结论:现在的计算机基本上都是多核,python对于计算密集型的任务开多线程的效率并不能带来多大性能上的提升,甚至不如串行(没有大量切换),但是,对于I/O密集型的任务效率还是有显著提升的。
问题:python多线程是不是就没用了?
四个任务:计算密集型的任务,每个任务耗时10s
单核情况下:
多线程好一点,消耗的资源少一点
多核情况下:
开四个进程:10s多一点
开多线程:40s多一点
四个任务:IO密集的任务 每个任务IO 10s
单核情况下:
多线程好一点
多核情况下:
多线程好一点
多线程和多进程都有自己的优点,要根据项目需求合理现在
引用: 多线程用于IO密集型,如socket,爬虫,web
多进程用于计算机密集型,如金融分析
多线程性能测试
#计算密集型:
from multiprocessing import Process
from threading import Thread import os,time
def work():
res=0
for i in range(10000000):
res*=i if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为4核
start=time.time()
for i in range(4):
p = Process(target=work) #进程耗时:1.7300989627838135
# p = Thread(target=work) #线程耗时:2.648151397705078
l.append(p)
p.start() for p in l:
p.join()
stop =time.time()
print('run time is %s'%(stop-start))
计算密集型:多进程效率高
#IO密集型:
from multiprocessing import Process
from threading import Thread
import os,time def work():
time.sleep(2) if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为4核
start=time.time()
for i in range(200):
p=Process(target=work) #进程耗时:9.763558387756348
# p=Thread(target=work) #线程耗时:2.020115852355957
l.append(p)
p.start() for p in l:
p.join()
stop=time.time()
print('run time is %s'%(stop-start))
I/O密集型:多线程效率高
GIL全局解释器的更多相关文章
- Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)
一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...
- Python自动化 【第九篇】:Python基础-线程、进程及python GIL全局解释器锁
本节内容: 进程与线程区别 线程 a) 语法 b) join c) 线程锁之Lock\Rlock\信号量 d) 将线程变为守护进程 e) Event事件 f) queue队列 g) 生 ...
- GIL全局解释器锁
1. 什么是GIL全局解释器锁 GIL本质就是一把互斥锁,相当于执行权限,每个进程内都会存在一把GIL,同一进程内的多个线程 必须抢到GIL之后才能使用Cpython解释器来执行自己的代码,即 ...
- 网络编程-Python高级语法-GIL全局解释器锁
知识点:GIL全局解释器锁其实和Python没有任何关系,是由于当初编写Python解释器时留下的,它只对多线程有影响,GIL保证同一时刻只有一个线程在运行,即使是多核配置电脑,同一时刻也只会让一个线 ...
- 进程、线程与GIL全局解释器锁详解
进程与线程的关系: . 线程是最小的调度单位 . 进程是最小的管理单元 . 一个进程必须至少一个线程 . 没有线程,进程也就不复存在 线程特点: 线程的并发是利用cpu上下文的切换(是并发,不是并行) ...
- python GIL :全局解释器
cpython 解释器中存在一个GIL(全局解释器锁),无论多少个线程.多少颗cpu 他的作用就是保证同一时刻只有一个线程可以执行代码,因此造成了我们使用多线程的时候无法实现并行. 因为有GIL的存在 ...
- [py]GIL(全局解释器锁):多线程模式
在多线程 时同一时刻只允许一个线程来访问CPU,直到解释器遇到I/O操作或者操作次数达到一定数目时才会释放GIL 参考 Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务.多个P ...
- 10 并发编程-(线程)-GIL全局解释器锁&死锁与递归锁
一.GIL全局解释器锁 1.引子 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 首先需要明确的一点是GIL并不是Python的特性,它是在实现Pyt ...
- [Python 多线程] GIL全局解释器锁 (十三)
Queue 标准库queue模块,提供FIFO(先进先出)的Queue.LIFO(后进先出)的队列.优先队列. Queue类是线程安全的,适用于多线程间安全的交换数据.内部使用了Lock和Condit ...
- 15 GIL 全局解释器锁 C语言解决 top ps
1.GIL 全局解释器锁:保证同一时刻只有一个线程在运行. 什么是全局解释器锁GIL(Global Interpreter Lock) Python代码的执行由Python 虚拟机(也叫解释器主循环, ...
随机推荐
- JS如何实现在微信中调用外部浏览器打开指定链接
使用方法,复制以下贴到index.php 顶部就可以了.场景 比如网页包含视频播放 在QQ\WX打开QQ\WX直接调用自己的播放器播放,而且播放完成还有AD推送,非常恶心,所以有了以下代码有乱码的话 ...
- Java关键字volatile的实现原理(四)
简述 volatile 是轻量级的synchronized,在多线程开发中保证了共享变量的可见性.可见性就是当一个线程修改一个共享变量时,另一个线程可以读到修改的值.如果volatile变量使用恰当, ...
- 关于Linux上面无法读取资源目录下文件的问题
一开始我的代码是这样子的,读取本地子路径下的json文件 代码运行的时候,在window是可以正常的 @Override public String getBannerStr() { String s ...
- 【零基础】搞懂GPU为什么比CPU“快”
一.前言 近几年深度学习在各领域大显神威,而”GPU加速"也得到了越来越多的篇幅,似乎任何程序只要放到GPU上运行那速度就是杠杠的.GPU代替CPU计算已成了大势所趋?我先告诉你结论”那是不 ...
- react-native(ios)简单配置环境(mac)
1.首先全局安装react-native-cli npm install -g react-native-cli 2.安装xcode(appStore) 3.打开xcode,检查一下是否装有某个版本的 ...
- Hibernate3核心API使用
public static void main(String[] args) throws Exception{ // 1. 加载默认的hibernate.cfg.xml的配置文件 Configura ...
- RabbitMQ学习之:(四)回头看刚才写的程序 (转贴+我的评论)
转自:http://lostechies.com/derekgreer/2012/03/18/rabbitmq-for-windows-hello-world-review/ 我的心得: 1. 在创建 ...
- 自定义nagios监控脚本---磁盘检测
自定义nagios监控脚本---磁盘检测 1. 在客户端上创建脚本/usr/local/nagios/libexec/check_disk.shvim /usr/local/nagios/libexe ...
- IDEA如何构建mybatis
任何一个软件都要和数据库关联,软件需要的数据都存储在数据库中. 对于经常使用的数据库相关的代码就出现了很多冗余的代码,持久层框架也随之出现. 目前使用比较流程的持久层框架有hibernate和myba ...
- 九十七:CMS系统之模板抽离和个人信息页面
模板抽取,将公共的页面抽出来作为模板 {% from 'common/_macros.html' import static %}<!DOCTYPE html><html lang= ...