一、GIL介绍

GIL本质就是一把互斥锁,既然是互斥锁,所有互斥锁的本质都一样,都是将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。

可以肯定的一点是:保护不同的数据的安全,就应该加不同的锁。

要了解GIL,首先确定一点:每次执行python程序,都会产生一个独立的进程。例如python test.py,python aaa.py,python bbb.py会产生3个不同的python进程

在一个python的进程内,不仅有test.py的主线程或者由该主线程开启的其他线程,还有解释器开启的垃圾回收等解释器级别的线程,总之,所有线程都运行在这一个进程内。

1、所有数据都是共享的

其中代码作为一种数据也是被所有线程共享的(test.py的所有代码以及Cpython解释器的所有代码)

2、所有线程的任务,都需要将任务的代码当做参数传给解释器的代码去执行,即所有的线程要想运行自己的任务,首先需要解决的是能够访问到解释器的代码

综上:

如果多个线程的target=work,那么执行流程是

多个线程先访问到解释器的代码,即拿到执行权限,然后将target的代码交给解释器的代码去执行

解释器的代码是所有线程共享的,所以垃圾回收线程也可能访问到解释器的代码而去执行,这就导致了一个问题:

对于同一个数据100,可能线程1执行x=100的同时,而垃圾回收执行的是回收100的操作,解决这种问题没有什么高明的方法?

就是加锁处理,如下图的GIL,保证python解释器同一时间只能执行一个任务的代码

二、GIL与Lock

GIL保护的是解释器级的数据,保护用户自己的数据则需要自己加锁处理,如下图

三、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对于计算密集型的任务开多线程的效率并不能带来多大性能上的提升,甚至不如串行(没有大量切换)

但是,对于IO密集型的任务效率还是有显著提升的。

四、多线程性能测试

1、计算密集型:多进程效率高

from multiprocessing import Process

from threading import Thread

import os,time

def work():

res=0

for i in range(100000000):

res*=i

l=[]

print(os.cpu_count()) #本机为4核

start=time.time()

for i in range(4):

# p=Process(target=work) #耗时18s多

p=Thread(target=work) #耗时26s多

l.append(p)

p.start()

for p in l:

p.join()

stop=time.time()

print('run time is %s' %(stop-start))

2、i/o密集型:多线程效率高

from multiprocessing import Process

from threading import Thread

import threading

import os,time

def work():

time.sleep(2)

print('===>')

l=[]

print(os.cpu_count()) #本机为4核

start=time.time()

for i in range(400):

p=Process(target=work) #耗时4s多,大部分时间耗费在创建进程上

# p=Thread(target=work) #耗时2s多

l.append(p)

p.start()

for p in l:

p.join()

stop=time.time()

print('run time is %s' %(stop-start))

应用:

多线程用于IO密集型,如socket,爬虫,web

多进程用于计算密集型,如金融分析

python gil_Python GIL(Global Interpreter Lock)相关推荐

  1. Python Basic - GIL:global interpreter lock(全局解释器锁)

    GIL:global interpreter lock(全局解释器锁) CPython implementation detail : in CPython,due to the Global Int ...

  2. python中GIL和线程与进程

    线程与全局解释器锁(GIL) 一.线程概论 1.何为线程 每个进程有一个地址空间,而且默认就有一个控制线程.如果把一个进程比喻为一个车间的工作过程那么线程就是车间里的一个一个流水线. 进程只是用来把资 ...

  3. Python的GIL是什么鬼,多线程性能究竟如何

    2019独角兽企业重金招聘Python工程师标准>>> #Python的GIL是什么鬼,多线程性能究竟如何 前言:博主在刚接触Python的时候时常听到GIL这个词,并且发现这个词经 ...

  4. python线程安全_线程,线程安全与python的GIL锁

    在看的过程中,接触到一个名词,一个从学python开始就一直看到,但是从来都是一知半解的名词,心里不开心,必须把它搞明白,对了,这个词就是 GIL.网上搜索了一些资料,粗浅的理解了什么是GIL,自己感 ...

  5. 对于python中GIL的理解

    一.什么是GIL GIL(Global Interpreter Lock)意为全局解释器锁.在这里先要明确几点: 1.python是解释型语言,也即什么时候需要用什么时候用解释器将其编译成机器语言,因 ...

  6. Python-GIL详解

    分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net GIL是什么 首先需要明确的一点是GIL并不是Pyt ...

  7. python gil锁存在的意义_对于Python的GIL锁理解

    GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可 ...

  8. 理解python的GIL

    UnderstandingGIL 个人笔记,有一点点修改,不喜右上角. 理解python的GIL 介绍 一个实验 结果 线程与GIL Python Threads 线程执行模型 cpu密集型任务 什么 ...

  9. Python 的GIL 和 互斥锁

    GIL 有 Python 开发经验的人也许听说过这样一句话:Python 不能充分利用 CPU 的多核优势. 为什么呢? 因为Python(Cpython) 中存在 GIL,即global inter ...

最新文章

  1. java 过滤器 加参数,自定义授权过滤器属性参数
  2. mysql 特殊字符
  3. 数字字符串转化为字母组合的种数
  4. firework常用快捷键
  5. Centos 7或者说linux 怎么一直运行一个项目,自己退出终端也在运行
  6. Marketing Cloud的contact主数据的odata调用方式
  7. springboot之websocket
  8. sqlsugar 批量删除guid类型主键_SAP使用MASS批量修改主数据
  9. Leetcode每日一题:37.sudoku-solver(解数独)
  10. java并发编程(3)--线程 有序性 volatile
  11. 推荐 几个神级 Java 开源学习项目
  12. ibm x3650 服务器安装系统安装,IBM服务器X3650安装操作系统步骤
  13. 服务器虚拟机迁移的过程和步骤是什么,物理机向虚拟机迁移过程详解
  14. C++ MFC学习笔记(第三课)绘制统计直方图
  15. 1. 抽纸片(java)
  16. 【小白】【大学】一名嵌入式软件开发小白的单片机学习历程、心路历程、经验分享
  17. 阿里云(AliCloud)简介
  18. 开发新设备设计时使用低温探针台的 8425 型直流霍尔系统
  19. 【夏季美女们穿的“清凉”容易引男生的狼眼】
  20. R语言学习笔记【简单语法总结-上】

热门文章

  1. 一个docker镜像中的目录删除不了问题
  2. windows环境下安装scrapy框架报错问题--最快捷有效的解决方案
  3. 【go网络编程】-RPC编程
  4. C++中的空类与空结构体大小
  5. 排优解难 网上邻居常遇故障解决方法
  6. 边缘会话控制器SBC
  7. python遇到Retry(total=4, connect=None, read=None, redirect=None, status=None)解决方案
  8. PAT甲级1023 Have Fun with Numbers:[C++题解]高精度加法和两个vector大小比较
  9. 中国人民大学_《组织行为学》_15如何降低集体决策的风险?
  10. wsl子系统添加开机启动任务