线程安全及Python中的GIL
线程安全及Python中的GIL
本博客所有内容采用 Creative Commons Licenses 许可使用. 引用本内容时,请保留 朱涛, 出处 ,并且 非商业 .
点击 订阅 来订阅本博客.(推荐使用 google reader, 如果你的浏览器不支持直接订阅,请直接在 google reader 中手动添加).
抱歉,在正文中加入很多本博客的链接,主要是发现很多转载的朋友并未按照本声明来加入出处信息. 影响阅读,实在抱歉.
摘要
什么是线程安全? 为什么python会使用GIL的机制?
在多核时代的到来的背景下,基于多线程来充分利用硬件的编程方法也不断发展起来, 但是一旦 牵扯到多线程,就必然会涉及到一个概念,即 线程安全, 本文就主要谈下笔者对线程安全的一些理解.
而Python为很多人所抱怨的一点就是GIL,那么python为什么选择使用GIL, 本文也就这个问题进行一些讨论.
引入
你的PC或者笔记本还是单核吗? 如果是,那你已经out了.
随着纳米技术的不断进步, 计算机芯片的工艺也在进步,但是已经很难在工艺上的改进来提高 运算速度而满足 摩尔定理, 所以intel, amd相继在采用横向的扩展即增加更多的CPU, 从而双核, 4核, N核不断推出,于是我们进入了多核时代.
于是一个问题出现了, 多核时代的出现对于我们程序员而言意味着什么, 我们如何利用多核的优势?
在回答这个问题之前,建议对 进程 和 线程 不熟悉的读者可以先补下相关的知识.
当然方案是,可以采用 多进程, 也可以采用 多线程. 二者的最大区别就是, 是否共享资源, 后者是共享资源的,而前者是独立的. 所以你也可能想起了google chrome为什么又开始使用独立的进程 来作为每个tab服务了(不共享数据,意味着有更好的安全性).
相对于进程的轻型特征,多线程环境有个最大的问题就是 如何保证资源竞争,死锁, 数据修改等.
于是,便有了 线程安全 (thread safety)的提出.
线程安全
Thread safety is a computer programming concept applicable in the context of multi-threaded programs.
A piece of code is thread-safe if it functions correctly during simultaneous execution by multiple threads.
In particular, it must satisfy the need for multiple threads to access the same shared data,
and the need for a shared piece of data to be accessed by only one thread at any given time.
上面是wikipedia中的解释, 换句话说, 线程安全 是在多线程的环境下, 线程安全能够保证多个线程同时执行时程序依旧运行正确, 而且要保证对于共享的数据,可以由多个线程存取,但是同一时刻只能有一个线程进行存取.
既然,多线程环境下必须存在资源的竞争,那么如何才能保证同一时刻只有一个线程对共享资源进行存取?
加锁, 对, 加锁可以保证存取操作的唯一性, 从而保证同一时刻只有一个线程对共享数据存取.
通常加锁也有2种不同的粒度的锁:
- fine-grained(所谓的细粒度), 那么程序员需要自行地加,解锁来保证线程安全
- coarse-grained(所谓的粗粒度), 那么语言层面本身维护着一个全局的锁机制,用来保证线程安全
前一种方式比较典型的是 java, Jython 等, 后一种方式比较典型的是 CPython (即Python).
前一种本文不进行讨论, 具体可参考 java 中的多线程编程部分.
至于Python中的全局锁机制,也即 GIL (Global Interpreter Lock), 下面主要进行一些讨论.
GIL
什么是 GIL ? 答案可参考wikipedia中的说明, 简单地说就是:
每一个interpreter进程,只能同时仅有一个线程来执行, 获得相关的锁, 存取相关的资源.
那么很容易就会发现,如果一个interpreter进程只能有一个线程来执行, 多线程的并发则成为不可能, 即使这几个线程之间不存在资源的竞争.
从理论上讲,我们要尽可能地使程序更加并行, 能够充分利用多核的功能, 那么Python为什么要使用 全局的 GIL 来限制这种并行呢?
这个问题,其实已经得到了很多的讨论, 不止十年, 可以参考下面的文档:
反对 GIL 的声音:
- An open letter to Guido van Rossum (这个文章值得一看,下面有很多的留言也值得一看)
认为 GIL 不能去除的:
- It isn't Easy to Remove the GIL (这个文章来自python作者 Guido, 他说明了什么要使用 GIL)
其它的一些讨论很容易从Google来搜索得到, 譬如: GIL at google.
那么,简单总结下双方的观点.
认为应该去除 GIL 的:
- 不顺应计算机的发展潮流(多核时代已经到来, 而 GIL 会很影响多核的使用)
- 大幅度提升多线程程序的速度
认为不应该去除 GIL 的(如果去掉,会):
- 写python的扩展(module)时会遇到锁的问题,程序员需要繁琐地加解锁来保证线程安全
- 会较大幅度地减低单线程程序的速度
后者是 Guido 最为关切的, 也是不去除 GIL 最重要的原因, 一个简单的尝试是在1999年(十年前), 最终的结果是导致单线程的程序速度下降了几乎2倍.
归根结底,其实就是多进程与多线程的选择问题, 有一段话比较有意思, 可以参考 http://www.artima.com/forums/flat.jsp?forum=106&thread=214235.
我引用如下:
I actually don't think removing the GIL is a good solution.
But I don't think threads are a good solution, either.
They're too hard to get right, and I say that after spending literally years studying threading in both C++ and Java.
Brian Goetz has taken to saying that no one can get threading right.
引自 Bruce Eckel 对 Guido 的回复. 而 Bruce Eckel 是何许人, 如果你了解 java 或者 C++, 那么应该不会不知道他.
个人的观点
那么,从我自己的角度来看(我没有太多的多线程编程经验), 先不论多线程的速度优势等,我更加喜欢多进程的是:
- 简单,无需要人为(或者语言级别)的加解锁. 想想 java 中的多线程编程,程序员通常会在此处出错(java程序员可以思考下)
- 安全, 这也是浏览器为什么开始使用多进程的一个原因
依照Python自身的哲学, 简单 是一个很重要的原则,所以, 使用 GIL 也是很好理解的.
当然你真的需要充分利用多核的速度优势,此时python可能并非你最佳的选择,请考虑别的语言吧,如 java, erlang 等.
转自:http://www.cnblogs.com/mindsbook/archive/2009/10/15/thread-safety-and-GIL.html
线程安全及Python中的GIL的更多相关文章
- 线程池与Python中的GIL
线程池是一个操作系统的概念,它是对多线程的一种优化. 多线程的时候,创建和销毁线程伴随着操作系统的开销,如果频繁创建/销毁线程,则会使效率大大降低. 而线程池,是先创建出一批线程放入池子里,需要创建线 ...
- Python中的GIL
•start 线程准备就绪,等待CPU调度 •setName 为线程设置名称 •getName 获取线程名称 •setDaemon 设置为后台线程或前台线程(默认) 如果是后台线程,主线程执行过程中, ...
- 聊聊Python中的GIL
对于广大写Python的人来说,GIL(Global Interpreter Lock, 全局解释器锁)肯定不陌生,但未必清楚GIL的历史和全貌是怎样的,今天我们就来梳理一下GIL. 1. 什么是GI ...
- 深入理解Python中的GIL(全局解释器锁)
深入理解Python中的GIL(全局解释器锁) Python是门古老的语言,要想了解这门语言的多线程和多进程以及协程,以及明白什么时候应该用多线程,什么时候应该使用多进程或协程,我们不得不谈到的一个东 ...
- Python中的GIL锁
在Python中,可以通过多进程.多线程和多协程来实现多任务. 在多线程的实现过程中,为了避免出现资源竞争问题,可以使用互斥锁来使线程同步(按顺序)执行. 但是,其实Python的CPython(C语 ...
- python中的GIL详解
GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可 ...
- 【转】Python中的GIL、多进程和多线程
转自:http://lesliezhu.github.io/public/2015-04-20-python-multi-process-thread.html 目录 1. GIL(Global In ...
- 关于python中的GIL
什么是GIL锁? GIL是Global Interpreter Lock的缩写,GIL中文可以称为全局解释器锁.提及到GIL,我们要知道它是在实现Python解析器(CPython)时所引入的一个概念 ...
- Python中对于GIL全局解释器锁的一点理解
GIL全局解释器锁 python最初开发时,开发人只考虑到了单核CPU的,为解决多线程运算之间的数据完整性和状态同步选择了加锁的方式.即GIL锁. 而目前的CPU都有多个核心,在运行python的某个 ...
随机推荐
- 为什么 input 元素能用 width 属性
前几天在是写网页的时候发现input可以设置宽高,很疑惑,上网查了之后发现: 简单的认为 input 就是 inline 元素是片面的.元素默认以何种 display 属性值显示出来,这个其实更多的时 ...
- Linux下查看tomcat连接数 .
netstat -na | grep ESTAB | grep 80 | wc -l 80是端口号
- sass/less/stylus css编译
早上来了听一同事说stylus如何才能编译成css文件,瞬时间有点蒙,一听感觉和less是差不多的功能,随着就上网去查,然后发现这个文章,介绍了这三种sass/less/stylus的安装和语法,贴在 ...
- 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序
这种错误的可能性有几种,比如: 1.没有安装数据访问组件,需要安装相应版本的数据访问组件: 2.没有安装相应版本的Office客户端,需要安装相应版本的Office客户端: 3.Microsoft.J ...
- 背景建模post_processing常用opencv函数(怒了)
1.saturate_cast<uchar>来说,就是把数据转换成8bit的0~255区间,负值变成0,大于255的变成255.如果是浮点型的数据,变成round最近的整数 2.cv::M ...
- [GodLove]Wine93 Tarining Round #7
比赛链接: http://vjudge.net/contest/view.action?cid=47643#overview 比赛来源: 2012 ACM/ICPC Asia Regional Han ...
- 刚写完的商城erp + 这个商城前台,新鲜出炉。自己1个人写, 包括php框架和前端html页面.
刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面.
- C#面向接口编程详解(1)——思想基础
我想,对于各位使用面向对象编程语言的程序员来说,“接口”这个名词一定不陌生,但是不知各位有没有这样的疑惑:接口有什么用途?它和抽象类有什么区别?能不能用抽象类代替接口呢?而且,作为程序员,一定经常听到 ...
- 【转载】Spark性能优化指南——高级篇
前言 数据倾斜调优 调优概述 数据倾斜发生时的现象 数据倾斜发生的原理 如何定位导致数据倾斜的代码 查看导致数据倾斜的key的数据分布情况 数据倾斜的解决方案 解决方案一:使用Hive ETL预处理数 ...
- JavaScript中字符串去掉特殊字符和转义字符
<pre name="code" class="javascript">/*** * 去掉字符串中的特殊字符 */ var excludeSpeci ...