Cpython解释器中的GIL全局解释器锁

1、什么是GIL全局解释器锁

  GIL:Global Interpreter Lock,意思就是全局解释器锁,这个GIL并不是Python的特性,他是只在Cpython解释器里引入的一个概念,而在其他的语言编写的解释器里就没有GIL,例如:Jython,Pypy等

  下面是官方给出的解释:

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython's memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

  翻译过来的意思就是:在CPython中,全局解释器锁(GIL)是一个互斥锁,可以防止多个本地线程同时执行Python字节码。这个锁是必要的,主要是因为CPython的内存管理不是线程安全的。(但是,由于GIL存在,其他特性已经发展到依赖于它所执行的保证。)

  所以:

    GIL本质上就是一把互斥锁,用来保证数据的正确性,使数据可以正常同步。

    GIL就像是BUG一般存在的全局互斥锁,目前无法通过代码去除GIL

  结论:在CPython解释器中,在同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势

  PS:我们平常所使用的python是C语言编写的,所以大部分人所说的python也指CPython,CPython是python的官方版本,若是指其他语言写的python,一般情况下会指明,如Jypthon、Pypy等

2、为什么会出现GIL

  随着电脑多核CPU的出现,python为了充分利用多核CPU,进行多线程的编程方式便普及了起来,但是随之而来的困难是线程之间数据的一致性和状态同步,python为了解决这个数据不能同步的问题,所以设计了GIL全局解释器锁,其实就是互斥锁

  说到互斥锁,在多线程互斥锁中共享全局变量的时候会有线程对全局变量进行的资源竞争,会对全局变量的修改产生不是我们想要的结果,而那个时候用到的是python中线程模块里面的互斥锁。

  如下例(未加线程互斥锁):

from threading import Threadimport time

n = 100
def task():
  global n
  m = n
  time.sleep(0.5)  # 模拟IO操作
  n = m - 1

if __name__ == '__main__':
  list1 = []
  for i in range(10):
    t = Thread(target=task)
    t.start()
    list1.append(t)

  for t in list1:
    t.join()

  print(n)

 执行结果:

99

  在上面的例子里,我创建了10个线程来争夺对 n 进行 -1 操作,但是结果并非我想要的,所以我在这里加入了互斥锁

  如下例(加线程互斥锁):

from threading import Thread
from threading import Lock
import time

n = 100
def task(lock):
  global n
  lock.acquire()  # 加锁
  m = n
  time.sleep(0.5)  # 模拟IO操作
  n = m - 1
  lock.release()  # 解锁

if __name__ == '__main__':
  list1 = []
  lock = Lock()
  for i in range(10):
    t = Thread(target=task, args=(lock, ))
    t.start()
    list1.append(t)

  for t in list1:
    t.join()

  print(n)

  执行结果:

90

  这次就可以得到我想要的结果

3、GIL的优缺点

  优点:

    保证数据的正确性

  缺点:

    单个进程下,开启多个线程,牺牲了执行效率,无法实现并行,只能实现并发

4、如何体现GIL全局解释器锁

  在Cpython解释器中,当python代码有一个线程开始访问解释器的时候,GIL会把这个大锁给锁上,此时此刻其他的线程只能干等着,无法对解释器的资源进行访问,这一点就和互斥锁相似。而只是这个过程发生在我们的Cpython中,同时也需要等这个线程分配的时间到了,这个线程把GIL释放掉,类似互斥锁的lock.release()一样,另外其他的线程才开始跑起来。

以上就是Cpython解释器中的GIL全局解释器锁的详细内容,更多关于GIL全局解释器锁的资料请关注我们其它相关文章!

时间: 2020-11-08

如何配置关联Python 解释器 Anaconda的教程(图解)

首先先安装好我们的Python 这里就不多介绍了 1.打开python.exe: 点击File 下的小扳手图标 Settings- 2.打开设置界面: 我们点击Project 这一栏下的 Project Interpreter 之后我们点击红色小方框 的小箭头 3.选择环境变量: 我们选择已有的两个环境变量中的其中一个 Python 3.7 点击下方的 Apply 等他加载成功后 我们点击OK 就完成了. 4.选择环境变量:另一种情况 我们发现下拉列表中没有可选择的环境变量时,点击右边的小齿轮,

Pycharm中安装wordcloud等库失败问题及终端通过pip安装的Python库如何添加到Pycharm解释器中(推荐)

这里介绍笔者在学习wordcloud库时安装过程中所遇到的问题和解决方案 1.在Pycharm中安装wordcloud出现的问题如下图所示 2.解决方法:在终端中通过wordcloud安装包安装方式,wordcloud的安装包下载链接:https://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud 选择与自己Python版本想对应的即可,这里笔者Python是3.8的所以选择图中标记的,版本选择不匹配将会安装错误,如下图所示: 下载完成后打开终端通过p

Atom Python 配置Python3 解释器的方法

环境 Mac Python3.6.4 Atom 背景 Atom 执行Python Code 使用Script Package,执行快捷键cmd + i. 但是默认是执行Mac 系统的2.7 版本的Python. 配置 cmd + ,(cmd + 逗号) 快捷键 打开Settings,或者点击Atom→Preferences 打开Settings 点击Open Config Folder(会打开Atom 的Project) 打开 .atom/packages/script/lib/grammars

mac 上配置Pycharm连接远程服务器并实现使用远程服务器Python解释器的方法

本文将介绍如何使用公司运行服务器进行开发调试,以及使用远程服务器python解释器,整理了对应的配置流程. 进入配置页面 Pycharm菜单栏,如下图所示,依次点击 Tools -> Deployment -> Configration- 开始配置连接服务器 1. Connection 选项设置: 具体参数说明: name 代码服务器配置名称 Type 协议类型,协议最好选择 SFTP Host.User name.Password 服务器配置相关信息 Root Path 为服务器项目运行的上

利用一个简单的例子窥探CPython内核的运行机制

我最近花了一些时间在探索CPython,并且我想要在这里分享我的一些冒险经历.Allison Kaptur的excellent guide to getting started with Python internals有一点啰嗦,我想逐步介绍我自己的探索过程会更加有条理性,这样也许其他好奇的Python使用者可以跟着一起做. 1.注意到了一些奇怪的事情 一开始,我只是设置好Nose对一些我写的Python 3代码进行测试.当我运行这些测试的时候,我得到了一个不可思议的错误信息:"TypeErr

python解释器pycharm安装及环境变量配置教程图文详解

1.python解释器安装 下载地址:https://www.python.org/ 打开官网,点击downloads,选择操作系统,以windows为例: 选择python2与python3解释器版本(以python3.6.6及python2.7.16为例): 以python3.6.6为例,根据操作系统下载不同安装包(python2.7.16类似) 下载完成后,双击打开,选择自定义安装: 点击完成后,选择下一步,修改默认安装路径(方便查找,添加环境变量),完成后点击安装 2.配置环境变量 右击

详解pycharm配置python解释器的问题

在这里选择使用哪个版本的interpreter: 下拉框里选择show all可以看见目前已有的 点击添加按钮: 可以选择system interpreter: 里面有所有现在电脑里安装的python,usr/bin/python和system目录下的是电脑自带的,usr/local/bin/python3是自己安装的.自己安装的python3是最底下的那个,这里usr下的,我理解为,是一种映射.usr/local/bin/python3是/Library路径下的python3的映射.因为我试了

安装好Pycharm后如何配置Python解释器简易教程

这两天有许多Python小白加入学习群,并且问了许多关于Pycharm基本使用的问题,今天小编就以配置Python解释器的问题给大家简单絮叨一下. 1.一般来说,当我们启动Pycharm,如果Pycharm正常激活的话,就会直接进入到Pycharm中去,并且Pycharm经常会弹出下图的界面.(如果有小伙伴的Pycharm尚未激活,可以站内私信,小编这有好几个激活码,给大家分享.) 其实这个是Pycharm的提示信息,一般是Pycharm的简易或快捷方式介绍或者其他的Pycharm功能说明,大家

PyCharm 配置远程python解释器和在本地修改服务器代码

最近在学习机器学习的过程中,常常需要将本地写的代码传到GPU服务器中,然后在服务器上运行.之前的做法一直是先在本地写好代码,然后通过FileZilla这样的文件传输工具来将写好的文件传到服务器,再通过ssh工具远程连接到服务器,执行相应的python脚本.这样的方式十分繁琐,效率很低.今天听到朋友提到了配置远程解释器 使用场景 先说说自己的使用场景,我是在什么情况下,需要将IDE配置成这样的环境来方便我的工作. 首先,我需要在本地机子上写python代码,但是因为是机器学习相关的一些代码,有时候

详解python编译器和解释器的区别

高级语言不能直接被机器所理解执行,所以都需要一个翻译的阶段,解释型语言用到的是解释器,编译型语言用到的是编译器. 编译型语言通常的执行过程是:源代码--预处理器--编译器--目标代码--链接器--可执行程序. 某种意义上来说预处理事实上是一个附加的功能,C,PHP,都可以添加这种功能,其中,预处理指令多为头文件包含,宏定义等等.因为宏定义的核心说白了就是一个字"换",所以预处理就是提供一个程序执行的环境. 编译器--目标代码就是把高级程序语言转换成机器可以理解执行的机器语言. 链接器的

详解Python中is和==的区别

在Python中一切都是对象. Python中对象包含的三个基本要素,分别是: id(身份标识) type(数据类型) value(值) 对象之间比较是否相等可以用 == ,也可以用 is . is 和 == 都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同.下面来看看具体区别在哪? is 比较的是两个对象的id值是否相等,也就是比较两个对象是否为同一个实例对象,是否指向同一个内存地址. == 比较的是两个对象的内容是否相等,默认会调用对象的 __eq__ 方法. == 是pytho

详解python中 os._exit() 和 sys.exit(), exit(0)和exit(1) 的用法和区别

详解python中 os._exit() 和 sys.exit(), exit(0)和exit(1) 的用法和区别 os._exit() 和 sys.exit() os._exit() vs sys.exit() 概述 Python的程序有两中退出方式:os._exit(), sys.exit().本文介绍这两种方式的区别和选择. os._exit()会直接将python程序终止,之后的所有代码都不会继续执行. sys.exit()会引发一个异常:SystemExit,如果这个异常没有被捕获,那

详解python方法之绑定方法与非绑定方法

写在之前 在 Python 的类里面除了属性之外,还有方法,当然也有文档和注释这类东西,但是这个只是人来看,计算机则不关心.我们之前说过,我们一般用实例调用方法,既然我们说了是一般,那么就说明还有其他调用方法的方式,今天我们就来说一下「绑定方法和非绑定方法」. 绑定方法和非绑定方法 在 Python 中除了特殊方法以外,类中的其他普通方法也是经常用到的,所以对于普通的方法也要进行研究,下面我们来看一个例子: >>> class Sample: ... def f(self): ... p

详解Python list 与 NumPy.ndarry 切片之间的对比

详解Python list 与 NumPy.ndarry 切片之间的区别 实例代码: # list 切片返回的是不原数据,对新数据的修改不会影响原数据 In [45]: list1 = [1, 2, 3, 4, 5] In [46]: list2 = list1[:3] In [47]: list2 Out[47]: [1, 2, 3] In [49]: list2[1] = 1999 # 原数据没变 In [50]: list1 Out[50]: [1, 2, 3, 4, 5] In [51]

详解python中的 is 操作符

大家可以与Java中的 == 操作符相互印证一下,加深一下对引用和对象的理解.原问题: Python为什么直接运行和在命令行运行同样语句但结果却不同,他们的缓存机制不同吗? 其实,高票答案已经说得很详细了.我只是再补充一点而已. is 操作符是Python语言的一个内建的操作符.它的作用在于比较两个变量是否指向了同一个对象. 与 == 的区别 class A(): def __init__(self, v): self.value = v def __eq__(self, t): return

详解Python自建logging模块

简单使用 最开始,我们用最短的代码体验一下logging的基本功能. import logging logger = logging.getLogger() logging.basicConfig() logger.setLevel('DEBUG') logger.debug('logsomething') #输出 out>>DEBG:root:logsomething 第一步,通过logging.getLogger函数,获取一个loger对象,但这个对象暂时是无法使用的. 第二步,loggi

详解python中asyncio模块

一直对asyncio这个库比较感兴趣,毕竟这是官网也非常推荐的一个实现高并发的一个模块,python也是在python 3.4中引入了协程的概念.也通过这次整理更加深刻理解这个模块的使用 asyncio 是干什么的? 异步网络操作并发协程 python3.0时代,标准库里的异步网络模块:select(非常底层) python3.0时代,第三方异步网络库:Tornado python3.4时代,asyncio:支持TCP,子进程 现在的asyncio,有了很多的模块已经在支持:aiohttp,ai

详解Python列表赋值复制深拷贝及5种浅拷贝

概述 在列表复制这个问题,看似简单的复制却有着许多的学问,尤其是对新手来说,理所当然的事情却并不如意,比如列表的赋值.复制.浅拷贝.深拷贝等绕口的名词到底有什么区别和作用呢? 列表赋值 # 定义一个新列表 l1 = [1, 2, 3, 4, 5] # 对l2赋值 l2 = l1 print(l1) l2[0] = 100 print(l1) 示例结果: [1, 2, 3, 4, 5] [100, 2, 3, 4, 5] 可以看到,更改赋值后的L2后L1同样也会被更改,看似简单的"复制"

详解python string类型 bytes类型 bytearray类型

一.python3对文本和二进制数据做了区分.文本是Unicode编码,str类型,用于显示.二进制类型是bytes类型,用于存储和传输.bytes是byte的序列,而str是unicode的序列. str类型: >>> s = u'你好' >>> s '你好' >>> type(s) <class 'str'> bytes类型: >>> b = b'abc' >>> b b'abc' >>&