004_浅析Python的GIL和线程安全

时间:2021-08-26 22:42:07

在这里我们将介绍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. Maven的环境搭建及新建web项目

    第一次接触maven,做一个简单的记录 一.下载maven及环境变量的配置 下载地址 http://maven.apache.org/download.cgi 配置其环境变量  MAVEN_HOME= ...

  2. 一些gcd计数问题

    数论什么的全都忘光了吧QAQ 做了几道简单的题练习一下. bzoj1101: [POI2007]Zap 求有多少对数满足 gcd(x,y)=d, 1<=x<=a, 1<=y<= ...

  3. java继承的对象中构造函数的调用顺序

    建立两个继承关系的对象 public class Machine { public String machieNameString; public Machine() { System.out.pri ...

  4. struts2校验の实现

    1.JSP <%@ page contentType="text/html; charset=utf-8" language="java" errorPa ...

  5. 解决SQLite数据库中文乱码问题

      关于SQLite中出现中文乱码的分析以及解决方案 我们在使用SQLite数据库时候,可能会发现,向数据库插入数据时候显示的是汉字,但通过SQLite读出来时却显示的乱码,这是因为SQLite数据库 ...

  6. 如何让linux时间与internet时间同步&lpar;centos&rpar;

    笔者在使用linux时(虚拟机),经常会发现使用一段时间后,linux时间和我的宿主机(真实机)的时间不一致,而宿主机的时间确实是internet时间,安装linux时选择的时区也是Asia/Shan ...

  7. 利用Java生成UUID

    UUID是什么? UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分.其目的,是 ...

  8. python网络爬虫与信息提取 学习笔记day2

    Day2: 查看robots协议: 查看京东的robots协议 查看百度的robots协议,可以看到百度拒绝了搜狗的爬虫233 爬取京东商品页面相关信息: import requests url = ...

  9. 1&period;Windows下使用VisualSVN Server搭建SVN服务器

    使用 VisualSVN Server来实现主要的 SVN功能则要比使用原始的 SVN和Apache相配合来实现源代码的 SVN管理简单的多,下面就看看详细的说明. VisualSVN Server的 ...

  10. linux c编程:文件的操作

    在Linux系统中,系统是通过inode来获得这个文件的信息.在Linux系统中,inode的信息都是封装在stat这个结构体中.可以通过man 2 stat来查看stat的具体结构.从中可以看到包含 ...