GIL锁                                                                                在CPython中,这个全局解释器锁,也称GIL,是一个互斥锁,防止多个线程在同一时间执行pyonty字节码,这个锁是非常重要的,因为cpython的内存管理非线程安全的,很多其他的特性依赖于GIL,所以即使它影响了程序效率也无法将其直接去掉。                                                       总结:在cpython中,GIL会把线程的并行变成串行,导致效率降低(需要的是知道的是,解释器并不是只有cpython,还有pypy,jpython等等。GIL也存在与cpython中,这并不是python这门语言的问题,而是cpython解释器的问题)

GIL与GC的孽缘

在使用Python中进行编程时,程序员无需参与内存的管理工作,这是因为Python有自带的内存管理机制,简称GC。那么GC与GIL有什么关联?

要搞清楚这个问题,需先了解GC的工作原理,Python中内存管理使用的是引用计数,每个数会被加上一个整型的计数器,表示这个数据被引用的次数,当这个整数变为0时则表示该数据已经没有人使用,成了垃圾数据。

当内存占用达到某个阈值时,GC会将其他线程挂起,然后执行垃圾清理操作,垃圾清理也是一串代码,也就需要一条线程来执行。

示例代码:

from threading import Thread
def task():
a = 10
print(a)

# 开启三个子线程执行task函数
Thread(target=task).start()
Thread(target=task).start()
Thread(target=task).start()

通过上图可以看出,GC与其他线程都在竞争解释器的执行权,而CPU何时切换,以及切换到哪个线程都是无法预支的,这样一来就造成了竞争问题,假设线程1正在定义变量a=10,而定义变量第一步会先到到内存中申请空间把10存进去,第二步将10的内存地址与变量名a进行绑定,如果在执行完第一步后,CPU切换到了GC线程,GC线程发现10的地址引用计数为0则将其当成垃圾进行了清理,等CPU再次切换到线程1时,刚刚保存的数据10已经被清理掉了,导致无法正常定义变量。

当然其他一些涉及到内存的操作同样可能产生问题问题,为了避免GC与其他线程竞争解释器带来的问题,CPython简单粗暴的给解释器加了互斥锁,如下图所示:有了GIL后,多个线程将不可能在同一时间使用解释器,从而保证了解释器的数据安全。

GIL的加锁与解锁时机

加锁的时机:在调用解释器时立即加锁

解锁时机:

  • 当前线程遇到了IO时释放

  • 当前线程执行时间超过设定值时释放

    GIL的优点:

    • 保证了CPython中的内存管理是线程安全的

    GIL的缺点:

    • 互斥锁的特性使得多线程无法并行

    但我们并不能因此就否认Python这门语言,其原因如下:

    1. GIL仅仅在CPython解释器中存在,在其他的解释器中没有,并不是Python这门语言的缺点

    2. 在单核处理器下,多线程之间本来就无法真正的并行执行

    3. 在多核处理下,运算效率的确是比单核处理器高,但是要知道现代应用程序多数都是基于网络的(qq,微信,爬虫,浏览器等等),CPU的运行效率是无法决定网络速度的,而网络的速度是远远比不上处理器的运算速度,则意味着每次处理器在执行运算前都需要等待网络IO,这样一来多核优势也就没有那么明显了

    1. 总结:

      1.单核下无论是IO密集还是计算密集GIL都不会产生任何影响

      2.多核下对于IO密集任务,GIL会有细微的影响,基本可以忽略

      3.Cpython中IO密集任务应该采用多线程,计算密集型应该采用多进程

    另外:之所以广泛采用CPython解释器,就是因为大量的应用程序都是IO密集型的,还有另一个很重要的原因是CPython可以无缝对接各种C语言实现的库,这对于一些数学计算相关的应用程序而言非常的happy,直接就能使用各种现成的算法

GIL锁的更多相关文章

  1. 53_并发编程-线程-GIL锁

    一.GIL - 全局解释器锁   有了GIL的存在,同一时刻同一进程中只有一个线程被执行:由于线程不能使用cpu多核,可以开多个进程实现线程的并发,因为每个进程都会含有一个线程,每个进程都有自己的GI ...

  2. python爬虫之多线程、多进程、GIL锁

    背景: 我们知道多线程要比多进程效率更高,因为线程存在于进程之内,打开一个进程的话,首先需要开辟内存空间,占用内存空间比线程大.这样想也不怪,比如一个进程用10MB,开10个进程就得100MB的内存空 ...

  3. python 线程(创建2种方式,锁,死锁,递归锁,GIL锁,守护进程)

    ###############总结############ 线程创建的2种方式(重点) 进程:资源分配单位    线程:cpu执行单位(实体) 线程的创建和销毁的开销特别小 线程之间资源共享,是同一个 ...

  4. 线程有gil锁

    gil锁作用: 遇到阻塞( 比如 recv() , accept() )就切换

  5. GIL锁、进程池与线程池

    1.什么是GIL? 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multip ...

  6. Python GIL锁

    GIL全局解释器锁:为了解决多线程修改同一块数据. python的线程是调用操作系统的源生线程,启动时就是调用C语言的C源生接口,python调用C语言接口的线程去执行任务时,必须上下文对应关系传给C ...

  7. day34 GIL锁 线程队列 线程池

    一.Gil锁(Global Interpreter Lock) python全局解释器锁,有了这个锁的存在,python解释器在同一时间内只能让一个进程中的一个线程去执行,这样python的多线程就无 ...

  8. day36 GIL锁与线程池

    多进程与多线程效率对比 # # """ # # 计算密集型 # """ # from threading import Thread # f ...

  9. GIL锁,线程池

    内容梗概: 1.线程队列 2.线程池 3.GIL锁 1.线程队列 1.1先进先出队列(FIFO)import queueq = queue.Queue(3)q.put(1)q.put(2)q.put( ...

随机推荐

  1. 洛谷P1972 【[SDOI2009]HH的项链】

    这道题想了很久,发题解是为了理解的更深刻一点...(管理放我过好嘛qwq) 步入正题:这道题应该是很多做法,我选择的是离线+树状数组. 首先输入数组.用fisrt数组先记录元素最开始出现的位置,对应的 ...

  2. Expression知识

    http://www.cnblogs.com/Ninputer/archive/2009/08/28/expression_tree1.html#!comments

  3. ES6 基础

    转载自:ES6 基础 一.新的变量声明方式 let/const 与var不同,新的变量声明方式带来了一些不一样的特性,其中最重要的两个特性就是提供了块级作用域与不再具备变量提升. 通过2个简单的例子来 ...

  4. day 11 - 1 装饰器

    装饰器 装饰器形成的过程:最简单的装饰器——有返回值的——有一个参数——万能参数装饰器的作用:不想修改函数的调用方式 但是还想在原来的函数前后添加功能原则:开放封闭原则语法糖:@装饰器函数名装饰器的固 ...

  5. win7用VMware安装CentOs7搭建Linux环境

    1. 首先要安装VMware 安装及破解教程 http://www.cnblogs.com/zhangqian27/p/9088237.html 2. 下载os镜像 CentOS下载地址: 阿里云开源 ...

  6. List与逗号分隔的字符串相互转换

    如果程序员想实现某种功能,有两条路可以走.一条就是自己实现,一条就是调用别人的实现,别人的实现就是所谓的API.而且大多数情况下,好多“别人”都实现了这个功能.程序员有不得不在这其中选择.大部分情况下 ...

  7. Java开发环境配置(2)--jdk配置和 多个JDK问题处理

    ==2018-8-15 16:41:06 更新 服务器 jdk1.6升级为1.8,没有卸载原来的1.6,直接安装1.8. 更改环境变量的 JAVA_HOME所指路径后, cmd 输入 java -ve ...

  8. Out of range value for column ""

    今天同事在初始化数据时,在初始手机号遇到如下报错:  我实体类的字段如下: @Column @Comment("购车人手机号") @ColDefine(type = ColType ...

  9. [TensorFlow笔记乱锅炖] tf.multinomial(logits, num_samples)使用方法

    tf.multinomial(logits, num_samples) 第一个参数logits可以是一个数组,每个元素的值可以简单地理解为对应index的选择概率,注意这里的概率没有规定加起来的和为1 ...

  10. Linux C 读取文件夹下所有文件(包括子文件夹)的文件名【转】

    转自:https://www.cnblogs.com/xudong-bupt/p/3504442.html 本文:http://www.cnblogs.com/xudong-bupt/p/350444 ...