哪些Python操作是原子性的?

与同事的一次对话使我意识到一个事实,那就是Python中相当大一部分操作都是原子的,即使像字典和类成员赋值这样的操作也是原子的。

为了完成像哈希表插入这样的操作,需要执行很多条机器语言指令,我很难想象这个操作居然是原子的。

为什么会这样?

Python FAQ提供了解释以及原子操作的完整列表,但简短的答案是:

Python字节码解释器只有在一个机器指令完成后,另一个机器指令没开始前,才会进行线程切换。

全局解释器锁(GIL)只允许一次执行一个线程。

很多操作都被转换为单个字节码指令。

使用dis包可以很容易的查看一个操作是否编译成单个字节码指令。

那么注意事项是什么? 依靠原子性而不是使用锁是否安全?

首先,上面的链接FAQ并没有说明这种行为多大程度上被认为是Python规范的一部分,还是CPython实现的情况。 它取决于GIL,所以在GIL-less Pythons(IronPython,Jython,PyPy-TM)上可能是不安全的。 在使用GIL(PyPy)的非CPython实现上安全吗? 我当然可以想象有些优化可能会使这些操作的原子性无效。

其次,即使不是绝对必要的,锁也提供了明确的线程安全保证,并且可以作为代码访问共享内存的有用说明。 如果没有锁,必须小心,因为很容易误把非原子操作假设成原子操作(postmortem 示例:Python的swap不是原子操作)。 一个明确的备注可能也是必要的,让合作者不必产生“等等,这可能需要一个锁!”的反应。

第三,因为Python允许重载如此多的内建方法,所以有些情况下这些操作不再是原子的。 Google Python风格指南建议:

不要依赖于内置类型的原子性。

虽然Python的内置数据类型(如字典)似乎具有原子操作,但是在某些情况下它们不是原子的(例如,如果将hash或eq实现为Python方法),并且不应该依赖它们的原子性。 你也不应该依赖于原子变量赋值(因为这又取决于字典)。

对于一般情况来说,遵循这个建议就够了。

在某些情况下,例如实现新的锁功能或性能至关重要时,可能仍然存在一些情况。 依靠操作的原子性有效地允许您在GIL上搭载锁定,从而降低额外锁的成本。 但是,如果锁的性能如此重要,你最好首先分析热点并寻找其他加速点。(也就是说,一般来说锁的性能不会如此重要)

那么在访问或修改共享可变状态时依赖操作的原子性是否合理呢?

简短的回答:

如果这样做,你最好有一个很好的理由。

你最好做一些彻底的研究,弄清楚其中的原理。

否则,你最好使用锁。

英文原文:http://blog.qqrs.us/blog/2016/05/01/which-python-operations-are-atomic/

译者:LJ

本文来自企鹅号 - Python程序员媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

【大牛经验】关于堆和栈的那些事

问题描述 编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么。我仅有高级语言编程经验,没有看过对此更清晰的解释。...

37590
来自专栏Java职业技术分享

使用Python这么多年,才发现Python还有这些实用的功能和特点

在使用Python多年以后,我偶然发现了一些我们过去不知道的功能和特性。一些可以说是非常有用,但却没有充分利用。考虑到这一点,我编辑了一些你应该了解的Pytho...

16330
来自专栏后端技术探索

什么是堆和栈,它们在哪儿?

编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么。我仅有高级语言编程经验,没有看过对此更清晰的解释。我的意思是...

11820
来自专栏WeTest质量开放平台团队的专栏

Unity手游崩溃异常如何捕获--C#及JVM捕获

C#脚本未捕获的异常,与Android和Native未捕获异常很大的区别是,未捕获异常不会照成引用的闪退。所以,C#脚本的异常危害相对较小,但是同样更加容易存在...

34240
来自专栏地方网络工作室的专栏

Shell 命令行求两个文件每行对比的相同内容

Shell 命令行求两个文件每行对比的相同内容 遇到的一个实际问题是,2017年08月01日起,所有未经实名的域名,全部停止解析。而我手上有不少域名,其中很多都...

28050
来自专栏祝威廉

Spark Tungsten in-heap / off-heap 内存管理机制前言

分析方式基本是自下而上,也就是我们分析的线路会从最基础内存申请到上层的使用。我们假设你对sun.misc.Unsafe 的API有一些最基本的了解。

12830
来自专栏PPV课数据科学社区

适用于 PHP 开发人员的 Python 基础知识

您是一名 PHP 开发人员。您在过去 五年(或更长时间)中可能一直都编写应用程序,您已经将许多想像变成了可能 — 电子商务系统、简单内容管理系统、Twitte...

414150
来自专栏老九学堂

【新手必读】Java初学者,你遇到的问题都在这了

很多小伙伴初次接触Java时往往会感觉十分迷茫,在这里老九君收集并解答了同学们遇到的一些基础问题,希望能对大家的Java学习之路有所帮助。 初识篇 1、什么是J...

39060
来自专栏向治洪

Android热修复技术总结

插件化和热修复技术是Android开发中比较高级的知识点,是中级开发人员通向高级开发中必须掌握的技能,插件化的知识可以查我我之前的介绍:Android插件化。本...

39270
来自专栏美团技术团队

Android插件化、热补丁中绕不开的ProGuard的坑

25660

扫码关注云+社区

领取腾讯云代金券