python 对象锁_也许你对 Python GIL 锁的理解是 错的。

84be82b1b10528633f0e752df0134e79.png

摄影:产品经理甜白与草莓更配~

我刚到现在这个公司时,听到当时一个高级工程师(现已离职)大声地跟他旁边的同事说:

Python 有 GIL 锁,所以它的多线程实际上是单线程,所以写多线程代码不用考虑线程冲突,不用加锁。

相信现在看这篇文章的同学,不少人也是这样认为的。

然而,我要告诉你的是,这句话前半句是对的,后半句是 错的。Python 的多线程确实本质上是单线程。但你依然需要考虑线程并发冲突。

我们来举个例子:

场景 1:单线程

变量 a 的值为1.代码读取 a 的值,把它加 1 变成2.然后把2重新赋值给 a。代码再次读取 a 的值,把它加 1 变成3.然后重新把3复制给 a。最终 a 的值是3.

场景 2:伪多线程

Python 的多线程是伪多线程,意味着在微观上它是单线程。同一个时间,只有一个线程在运行,其他线程是暂停的状态。现在有一个变量 a,它里面的值为1.

  1. 线程 1 从 a 里面获取到1,把它加1,线程 1 还没有来得及把数字2重新赋值给变量 a 时,时间片切换到线程 2.
  2. 此时线程 1 暂停。线程 2 去读取变量 a,这个时候的 a 依然是1.线程 2 也把这个数字加1,变成2.
  3. 时间片切换到线程 1,线程 2 暂停。线程 1 把数字2赋值给变量 a,此时 a 的值变成2.
  4. 时间片切换到线程 2,线程 1 暂停。线程 2 把数字2赋值给变量 a,此时 a 的值还是2.

可以看到,即使同一时间只有一个线程在运行,但是两个线程同时修改同一个变量时,也会发生并发冲突。

GIL 到底锁的是什么?

大家都说 Python 有 GIL 锁,那么这个锁到底锁的是什么东西??

GIL 的全称是 Global Interpreter Lock, 全局解释器锁。它锁的是解释器而不是你的 Python 代码。它防止多线程同时执行 Python 的字节码(bytecodes),防止多线程同时访问 Python 的对象。

在 Python 官方文档Releasing the GIL from extension code[1]中,有这样一段话:

Here is how these functions work: the global interpreter lock is used to protect the pointer to the current thread state. When releasing the lock and saving the thread state, the current thread state pointer must be retrieved before the lock is released (since another thread could immediately acquire the lock and store its own thread state in the global variable). Conversely, when acquiring the lock and restoring the thread state, the lock must be acquired before storing the thread state pointer.

其中加黑的这一句话是说:GIL 锁用来保护指向当前进程状态的指针。

再看文档Thread State and the Global Interpreter Lock[2]中提到的这样一句话:

Without the lock, even the simplest operations could cause problems in a multi-threaded program: for example, when two threads simultaneously increment the reference count of the same object, the reference count could end up being incremented only once instead of twice.

当两个线程同时提高同一个对象的引用计数时,(如果没有 GIL 锁)那么引用计数只会被提高了 1 次而不是 2 次。

大家注意我这两段应用中的指针引用计数。其中指针是 C 语言的概念,Python 没有指针;引用计数是 Python 底层的概念。你平时写的 Python 代码,引用计数是在你调用变量的时候自动增加的,不需要你去手动加 1.

所以 GIL 锁住的东西,都是不需要你的代码直接交互的东西。

Python 的解释器通过切换线程来模拟多线程并发的情况,如上面举的例子,虽然同一个时间只有一个线程在活动,但仍然可以导致并发冲突。

所以,以后不要再说出 Python 不需要解决并发冲突这种话了。

参考资料

[1]

Releasing the GIL from extension code: https://docs.python.org/3/c-api/init.html#releasing-the-gil-from-extension-code

[2]

Thread State and the Global Interpreter Lock: https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock

a45bdca81d97dd0680945fc004551c1b.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346248.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务性服务–服务到服务的通话

在上一篇文章中,我介绍了如何使用Knative的 Serving功能来运行示例Java应用程序。 这篇文章将介绍部署两个应用程序的步骤,其中一个应用程序调用另一个。 样品细节 整个示例可在我的github存储库中找到– https://github.com/bijukunjummen/sleuth-webf…

linux cookie 地址,SYN Cookie原理及其在Linux内核中的实现

在目前以IPv4为支撑的网络协议上搭建的网络环境中,SYN Flood是一种非常危险而常见的DoS攻击方式。到目前为止,能够有效防范SYN Flood攻击的手段并不多,而SYN Cookie就是其中最著名的一种。SYN Cookie原理由D. J. Bernstain和 Eric Schenk发明…

用置换破坏您的JUnit5测试

编写JUnit测试可能是一个乏味而乏味的过程。 了解如何使用排列结合TestFactory方法和DynamicTest对象以最少的编码工作来改进测试类。 在本文中,我将使用Java流ORM Speedment,因为它包含一个现成的Permutation类,从而帮助我节省了开发时间。…

企业应用程序开发框架的分类

如果您使用的是“最佳Java框架”,那么您很可能会迷失本文 ,它对Java Enterprise世界中的情况进行了很好的概述。 但是,从我的角度来看,它缺少一件非常重要的事情–对上述框架进行分类。 让我们看看这个生态系统的另一个角度&…

c语言中怎么定义的字符串,C语言中定义字符串的几种方式

1,什么是字符串?所谓字符串本质上就是以\0作为结尾的特殊字符数组;2,定义字符串的过程中有哪些注意点由于字符串本质上其实就是以\0作为结尾的特殊字符数组,所以定义字符串时,必须保证字符串存储的最后一个…

java8 linq4j_Java 8仍然需要LINQ吗? 还是比LINQ更好?

java8 linq4j长期以来, LINQ是.NET软件工程生态系统中发生的最好的事情之一。 通过在Visual Studio 2008中引入lambda表达式和monad ,它使C#语言跃居Java之前,Java在当时是版本6,但仍在讨论泛型类型擦除的优缺点。 这项…

mongodb上一篇下一篇_如何使用Microsoft office word—上一篇

从这一期开始,将会逐一介绍Microsoft office的几个常用的软件,例如word ppt excel等,每一个软件将分为几期介绍,这几期介绍word。注意:介绍软件版本是Microsoft office365。如何插入图片首先打开word,点击插…

Istio的零停机滚动更新

本系列文章的第一部分介绍了如何在Kubernetes集群中实现真正的零停机时间更新。 我们专门解决了将流量从旧实例切换到新实例时出现的请求失败。 本文将展示如何使用Istio群集实现相同的目标。 服务网格技术(例如Istio)通常与容器编排结合使用。 Istio以…

android 设置资源,Android 资源

Android 资源Android Resources02/01/2018本文内容本文介绍了 Xamarin 中 Android 资源的概念,并介绍了如何使用这些资源。其中介绍了如何使用 Android 应用程序中的资源来支持应用程序本地化和多个设备,包括不同的屏幕大小和密度。This article introdu…

仿小黄车android定位,小黄车ofo是怎么实现自行车定位功能的?

摩拜单车通过车身携带的GPS而实现单车定位,但是我们知道ofo是没有安装GPS,它又是如何实现单车定位的呢?我居住的地方距离地铁站步行大约15分钟左右,距离最近的商场步行将近30分钟,距离周边的便利店,水果店,饭店等步行1…

gprs连接中断记录_请收好!脉搏波血压计连接天天血压APP使用指南

总有那么几个粗心的小伙伴丢失了说明书,在后台追问波哥如何连接“天天血压”,于是给大家安排了这篇使用指南。首先我们来了解下“天天血压”的功能:1.通过蓝牙或GPRS传输,同步记录每次测量结果;2. 血压趋势分析&#x…

使用Spring Boot,JHipster和React构建照片库PWA

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。 从本质上讲,React只是一个UI工具包,即ala GWT,但是…

names文件和data文件_data.table让你的读取速度提升百倍

不知道大家有没有用read.table和read.csv读取过文件,当文件不大的时候你可能还感觉不出读取速度,但是当文件比较大的时候,比如有上万行的时候,你就会感觉到等待时间明显变长,甚至无法忍受。今天小编给大家安利一个实用…

差分放大电路差模共模公式_提高差分放大器的共模抑制比,电阻的选择很关键...

在各种应用领域,采用模拟技术时都需要使用差分放大器电路。例如测量技术,根据其应用的不同,可能需要极高的测量精度。为了达到这一精度,尽可能减少典型误差源(例如失调和增益误差,以及噪声、容差和漂移)至关重要。为此…

label标签 html5,HTML5 label 标签

实例HTML5 标签用于为 input 元素做出标记。带有两个输入字段和相关标记的简单 HTML 表单:MaleFemale尝试一下 浏览器支持目前大多数浏览器支持 标签。标签定义及使用说明标签为 input 元素定义标注(标记)。label 元素不会向用户呈现任何特殊效果。不过,…

me shy是什么歌 抖音make_抖音星河滚烫你是人间的理想下一句是什么歌 星河歌词完整版...

最近在抖音上听到一段话,这段话的开头是“星河滚烫,你是人间的理想……”。抖音星河滚烫你是人间的理想下一句是什么歌?星河歌词介绍?星河,是非常好听的一首歌曲,是很多人都喜欢的一首歌曲。抖音星河滚烫你…

修改使用计算机的名称,Windows 10中修改计算机名称的方法,你知道几种?

当用户新入手一台电脑时,通常做的第一件事就是做一些个性化设置。一般来说个性化的第一步就是给计算机起一个自己满意的名字,下面介绍几种修改计算机名字的方法。通过设置更改计算机名字按WinI键进入设置,在设置窗口中找到“系统”,点击它。在…

apollo 参数传递_使用Apollo通过WebSocket通过STOMP轻松进行消息传递

apollo 参数传递在我以前的文章中,我介绍了几个有趣的用例,这些用例使用著名的消息代理HornetQ和ActiveMQ通过Websockects实现STOMP消息传递。 但是我没有介绍的是Apollo,因为我个人认为它的API是冗长的,并且不像Java开发人员那样…

使用IntelliJ调试Java流

流功能非常强大,只需几行就可以捕获您预期功能的要点。 但是,就像它们在一切正常工作时一样平滑,就像它们在表现不正常时一样令人痛苦。 了解如何使用IntelliJ调试Java Streams并深入了解Stream的中间操作。 在本文中,我将在示例…

echart 饼图每一块间隙_花10分钟做酱香饼,简单方便又美味,酥脆咸香比买的还要好吃...

花10分钟做酱香饼,简单方便又美味,酥脆咸香比买的还要好吃前几年,在单位附近有一家只做酱香饼的小店,刚开张的时候排很长队,我为了一块酱香饼排队半小时。后来买酱香饼的人少了,我三天两头买一块酱香饼解馋…