python多线程机制
Python中的线程从一开始就是操作系统的原生线程。而Python虚拟机也同样使用一个全局解释器锁(Global Interpreter Lock,GIL)来互斥线程多Python虚拟机的使用。
- GIL与线程调度
为了理解Pyhon为什么需要GIL,考虑这样的情形:假设有两个线程A B,在两个线程中,都同时保存着对内存中同一对象obj的引用,也就是说,这事obj->ob_refcnt的值为2.如果A销毁对obj的引用,显然,A将通过Py_DECREF调整obj的引用计数值。外面知道,py_DECREF的整个动作可以分为两个部分:
--obj ->ob_refcnt;
if(obj->ob_refcnt == 0) destory object and free memory.
如果A执行完第一个动作后,obj->ob_refcnt的值变为1,不幸的是,在这里时候线程调度机制将A挂起,唤醒了B。更为不幸的是,B同样也开始销毁对obj的引用。B完成第一个动作后,obj ->ob_refcnt为0,B是一个幸运儿,它没有被线程调度打断,而是顺利完成了接下来的第二个动作,将对象销毁,内存释放。好了吗,现在A又被重新唤醒,可现在已是物是人非,obj ->ob_refcnt已经被B减少到0,而不是当时的1.按照约定,A开始在一次地对已经销毁的对象进行对象销毁的内存释放动作。结局是什么?只有天知道………………
为了支持多线程机制,一个基本的要求就是需要实现不同线程对共享资源访问的互斥。Python也不例外,这正是引入GIL的根源所在。Python中的GIL是一个非常霸道的互斥实现,正如它的名字所暗示的,GIL是一个解释器(Interpreter)。也就是说,在一个线程拥有了解释器的访问权之后,其他的所有线程都必须等待它释放解释器的访问权,即使这些线程的下一条指令并不会互相影响。初看上去,这样的保护机制粒度太大了,我们似乎只需要将可能被多个线程共享的资源保护起来即可,对于不会被多个线程共享的资源,完全可以不用保护。实际上,在Python发展的历史中,的确出现过这样的解决方案,但令人惊奇的,这样的方案在单处理器上的多线程实现效率上却没有GIL的方案好,所以现在python中的多线程机制是在GIL的基础上实现的。
当然,这样的方案也就意味着,无论如何,在同一时间,只能有一个线程能访问python所提供的API。注意这里的同一时间对于单处理器是毫无意义的,因为单处理器的本质是不可能并行的,但是多处理器就完全不同了,同一时间,的确可以有多个线程独立运行,然而python的GIL限制了这样的情形,是的多处理器最终退化为单处理器,性能大打折扣。
2.
对于python而言,字节码解释器是python的核心所在,所以Python通过GIL来互斥不用线程对解释器的使用。
如图所示,A B C都需要使用解释器来执行字节码,以完成某种计算,但是在这之前,他们必须获得GIL,因为GIL把守这通往字节码解释器的大门。当A获得GIL之后,其他两个线程B C只能等待A释放GIL后,才能进入解释器,执行一些计算。
实际上,Python的GIL背后所保护的不仅仅是Python的解释器,同样还有Python的C API,在C/C++和Python的混合开发中,在涉及到原生线程和Python线程的相互协作时,也需要GIL进行互斥。
那么A在何时释放GIL呢?如果等到A使用完解释器之后,才释放GIL,这也就意味着,并行计算退化了为了串行的计算,毫无疑问,Python拥有一探线程的调度机制。
对于线程的调度机制而言,同操作系统的进程调度一样,最关键要解决两个问题:
- 在何时挂起当前的线程,选择处于等待状态的下一个线程?
- 在众多的处于等待状态的线程中,选择激活哪一个线程?
在python多线程的机制中,这两个问题是分别由不同的层次解决的。对于何时进行线程调度的问题,是由python自身决定的。考虑一下操作系统是如何进行进程的切换的。当一个进程执行了一段时间后,发生了时钟中断,操作系统响应时钟中断,并在这时开始进行进程的调度。同样,python中也是通过软件模拟了这样的时钟中断,来激活线程的调度。我们知道,python的字节码解释器的工作原理是按照指令的顺序一条一条的顺序执行,Python内部维护着一个数值,这个数值就是Python内部的时钟,如果这个数值为N,则意味着Python在执行了N条指令以后应该立即启动线程调度机制。
import sys
print sys.getcheckinterval()
上面代码的执行结果,Python默认是在执行了100条指令后启动线程调度机制。实际上,这个值不仅仅用来进行线程调度,在内部,Python也使用它来检查是否有异步的时间(envent)发生,需要处理。我们可以通过 sys.setcheckinterval() 来调节这个值。
那么究竟python会在众多等待线程中选择哪一个幸运儿呢?答案是,不知道。对于这个问题,Python完全没有插手,而是交给了底层的操作系统来解决。也就是说python借用了底层操作系统所提供的线程调度机制来决定下一个进入Python解释器的线程究竟是谁。
这一点至关重要,这就意味着Python中的线程实际上就是操作系统所支持的原生线程,并不是模拟出来的。Python中的多线程机制也是建立在操作系统的原生线程的基础之上,对应不同的操作系统,有不同的实现,然而最终,在不同的原生线程基础上,Python提供了一套统一的抽象机制,给Python的使用者一个非常简单而方便的多线程工具箱,这就是python中的两个Module:thread以及在其之上的threading。
python多线程机制的更多相关文章
- day-3 python多线程编程知识点汇总
python语言以容易入门,适合应用开发,编程简洁,第三方库多等等诸多优点,并吸引广大编程爱好者.但是也存在一个被熟知的性能瓶颈:python解释器引入GIL锁以后,多CPU场景下,也不再是并行方式运 ...
- Python GIL 多线程机制 (C source code)
最近阅读<Python源码剖析>对进程线程的封装解释: GIL,Global Interpreter Lock,对于python的多线程机制非常重要,其如何实现的?代码中实现如下: 指向一 ...
- 【python,threading】python多线程
使用多线程的方式 1. 函数式:使用threading模块threading.Thread(e.g target name parameters) import time,threading def ...
- <转>Python 多线程的单cpu与cpu上的多线程的区别
你对Python 多线程有所了解的话.那么你对python 多线程在单cpu意义上的多线程与多cpu上的多线程有着本质的区别,如果你对Python 多线程的相关知识想有更多的了解,你就可以浏览我们的文 ...
- Python多线程和Python的锁
Python多线程 Python中实现多线程有两种方式,一种基于_thread模块(在Python2.x版本中为thread模块,没有下划线)的start_new_thread()函数,另一种基于th ...
- 【跟我一起学Python吧】Python 多线程
其实自我感觉Python的多线程很类似于Java的多线程机制,但是比JAVA的多线程更灵活.在早期的Python多线程实现中,采用了thread模块.例如: from time import ctim ...
- 搞定python多线程和多进程
1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...
- Python多线程练习(threading)
这几天学习python多线程的时候,试了几次thread模块和threading模块,发现thread模块非常的不好用.强烈不建议大家使用thread,建议使用threading模块,此模块对thre ...
- 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼
1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...
随机推荐
- Android使用 selector 自定义控件背景 (以spinner 为例)
1. 在drawable中设置背景spinner_style.xml 文件 如图: 2. 在 styles.xml 中添加该背景 3. 最后在 spinner 控件添加样式 4.参考 http:// ...
- angularjs ngTable -Custom filter template-calendar
jsp页面: <script type="text/ng-template" id="path/to/your/filters/top-Date-One.html& ...
- Two ways to create file using 'doc'.
Here are two ways to create file using 'doc' command: Method i: copy con [file name][enter key] [con ...
- Creating a web application.
About creating web GIS applications As you learn and use ArcGIS for Server, you'll probably reach th ...
- App上线基本流程
还可参考的:http://www.cocoachina.com/bbs/read.php?tid=330302 iOS项目上传前期准备材料: 1.已有开发者账号 2.已有发布证书 3.一张1024*1 ...
- Visual Studio vs2010 去掉中文注释红色下划线;去掉代码红色下划线;
vs去掉下挂线也分两种: 1.去掉中文注释红色下划线,需要去掉VisualAssist下划线鸡肋功能: 1.选择Visual AssistX Options: 2.把如图所示的勾去掉,解决. 以后再次 ...
- js浏览器键盘事件控制(转自新浪微博)
js键盘事件全面控制 主要分四个部分第一部分:浏览器的按键事件第二部分:兼容浏览器第三部分:代码实现和优化第四部分:总结 第一部分:浏览器的按键事件 用js实现键盘记录,要关注浏览器的三种按键事件类型 ...
- C#DataTable操作
] 在DataSet中添加DataTable DataSet.Tables.Add(DataTable) 实例: DataSet ds=new DataSet(); DataTable table=n ...
- Html5新增加的属性
用2中方法给单复选框增加新的特性,使直接点击文字就可以被选中 1.将选项放入label标签内添加for属性,并在input标签内添加id,两者值相同. 2.将input标签放到label标签内,注意l ...
- #module-django.db.models
Models A model is the single, definitive source of information about your data. It contains the esse ...