在这里我们将介绍Python的GIL和线程安全,希望大家能从中理解Python里的GIL,以及GIL的前世今生。

对于Python的GIL和线程安全很多人不是很了解,通过本文,希望能让大家对Python的GIL等内容有所帮助。本文还将就主要谈下笔者对线程安全的一些理解。

摘要

什么是线程安全? 为什么Python会使用GIL的机制?

在多核时代的到来的背景下,基于多线程来充分利用硬件的编程方法也不断发展起来, 但是一旦 牵扯到多线程,就必然会涉及到一个概念,即 线程安全, 本文就主要谈下笔者对线程安全的一些理解.

而Python为很多人所抱怨的一点就是GIL,那么Python为什么选择使用GIL, 本文也就这个问题进行一些讨论.

Contents

摘要 引入 线程安全 GIL 个人的观点 参考资料 本文的rst源码 . 引入

你的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), 下面主要进行一些讨论.

Python的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 等.

原文标题:线程安全及Python中的GIL

链接:http://www.cnblogs.com/mindsbook/archive/2009/10/15/thread-safety-and-GIL.html

004_浅析Python的GIL和线程安全的更多相关文章

  1. python中GIL和线程与进程

    线程与全局解释器锁(GIL) 一.线程概论 1.何为线程 每个进程有一个地址空间,而且默认就有一个控制线程.如果把一个进程比喻为一个车间的工作过程那么线程就是车间里的一个一个流水线. 进程只是用来把资 ...

  2. 【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)

    GIL锁 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行的, ...

  3. Python GIL、线程锁、信号量及事件

    GIL是什么? GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码.有名的编 ...

  4. python并发编程之线程(创建线程,锁(死锁现象,递归锁),GIL锁)

    什么是线程 进程:资源分配单位 线程:cpu执行单位(实体),每一个py文件中就是一个进程,一个进程中至少有一个线程 线程的两种创建方式: 一 from threading import Thread ...

  5. 深入浅析python中的多进程、多线程、协程

    深入浅析python中的多进程.多线程.协程 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源 ...

  6. python之进程与线程

    什么是操作系统       可能很多人都会说,我们平时装的windows7 windows10都是操作系统,没错,他们都是操作系统.还有没有其他的? 想想我们使用的手机,Google公司的Androi ...

  7. python学习道路(day10note)(线程,进程)

    1.计算机的发展史 看alex的博客吧,了解一下可以了 2.线程与GIL简介 #线程 #一道单一的指令的控制流,寄生在进程中 #单一进程里的多个线程是共享数据的 #多个线程涉及修改共享数据的时候需要枷 ...

  8. python学习笔记12 ----线程、进程

    进程和线程的概念 进程和线程是操作系统中两个很重要的概念,对于一般的程序,可能有若干个进程,每一个进程有若干个同时执行的线程.进程是资源管理的最小单位,线程是程序执行的最小单位(线程可共享同一进程里的 ...

  9. [转载] Python的GIL是什么鬼,多线程性能究竟如何

    原文: http://cenalulu.github.io/python/gil-in-python/ GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器( ...

随机推荐

  1. [小知识点] react 性能

    场景: jsx 绑定方法 方法有3种 1: // 在html中,使用箭头函数,自动绑定this class SearchHistory extends React.Component {      c ...

  2. js 实现 0-9 随机排序

    function randomsort(a, b) {return Math.random()>0.5 ? -1 : 1;//用Math.random()函数生成0~1之间的随机数与0.5比较, ...

  3. node(http, url)

    一.http 模块 http.js const http = require('http'); const hostname = '127.0.0.1'; const port = 3000; con ...

  4. html/css的学习之路(2)

    今天我跟大家说一下html,html里面其实什么东西都可以放进去的.首先创建一个文本,改变他的后缀名为html.这时有个最重要的一点不管是html还是css都不可以用中文和符号命名. 这是html中的 ...

  5. Java 开源博客 Solo 1.9.0 发布 - 新皮肤

    这个版本主要是改进了评论模版机制,让大家更方便皮肤制作,并发布了一款新皮肤:9IPHP. Solo 是一款一个命令就能搭建好的 Java 开源博客系统,并内置了 15+ 套精心制作的皮肤.除此之外,S ...

  6. 网络控制器intel 82599, powerpc 830的BD描述符结构

    一.Intel 82599的BD结构 1.文档名称“82599-10-gbe-controller-datasheet.pdf”,可以从intel官网上下载. https://www.intel.cn ...

  7. Android为TV端助力 布局、绘制、内存泄露、响应速度、listview和bitmap、线程优化以及一些优化的建议!

    1.布局优化 首先删除布局中无用的控件和层级,其次有选择地使用性能较低的viewgroup,比如布局中既可以使用RelativeLayout和LinearLayout,那我们就采用LinearLayo ...

  8. 一次电话Java面试的问题总结(JDK8新特性、哈希冲突、HashMap原理、线程安全、Linux查询命令、Hadoop节点)

    面试涉及问题含有: Java JDK8新特性 集合(哈希冲突.HashMap的原理.自动排序的集合TreeSet) 多线程安全问题 String和StringBuffer JVM 原理.运行流程.内部 ...

  9. <1>Linux日志查找方法

    Linux日志查找方法 适用于测试,开发,运维人员,用来查找Linux服务器问题的一般方法,比较实用,如果有更好的办法可以一块讨论,欢迎大神们来指导哈!!! 进入正题 第一步.通过Xshell登录服务 ...

  10. (网页)websocket后台调用Service层

    百度论坛里面有很多好的方法,借鉴. 重点:因为项目是StringBoot所以我用的是下面的方法很好使: Service.... service = (Service....) ContextLoade ...