开发者社区> ghost丶桃子> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

python 多线程

简介:
+关注继续查看

真正的多线程吗?

对于多核处理器,在同一时间确实可以多个线程独立运行,但在Python中确不是这样的了。原因在于,python虚拟机中引入了GIL这一概念。GIL(Global Interpreter Lock)全局解析器锁是用来解决共享资源访问的互斥问题,导致在python虚拟机中同一时间只能有一个线程访问python所提供的API。

那么python是如何支持多线程的呢?

在操作系统中系统通过时钟中断进行进程的调度,而python正是参考这个原理。在python内部维护了一个内部的时钟,来记录每个线程每个时钟周期执行命令的数量。

>>> import sys
>>> sys.getcheckinterval() #获取一个始终周期内执行指令数
100

当一个线程获得了python虚拟机的GIL后可以按顺序执行100条指令,然后挂起当前进程,切换下一个等待执行的线程。

那么python如何选择下一个需要执行的线程呢?

python并没有去实现一个线程优先级调度算法,而是将线程选择问题交给了底层的操作系统,也就是说python借用了底层操作系统所提供的线程调度机制来决定下一个执行的线程。

因此,python使用的就是操作系统原生的线程,只是python在其基础之上提供了一套统一的抽象机制。

线程切换

在操作系统中,进程之间的切换需要不断保存和恢复进程之间的上下文环境,保证每一个进行都能在其对应的上下文环境中运行。python正是参考操作系统的切换机制,为每一个线程创建一个保存线程状态信息的PyFrameObject对象。在python中有有一个全局变量PyThreadState *_PyThreadState_Current用来保存当前活动线程的线程状态对象。

下一线程切换需要的线程状态如何获取?

在python中通过一个单项链表来管理所有的python线程对象(保护线程的状态信息和线程信息,例如线程id),当需要寻找一个线程对应的状态对象时,就遍历这个链表,搜索其对应的状态对象。

这个状态对象链表并不会受到GIL的保护,而是有其专用的锁。

需要注意

当前活动的python线程不一定是获得了GIL的线程,例如“主线程获得了GIL,子线程还没有申请到GIL时也没有挂起,而且主线程和子线程都是操作系统原生的线程,操作系统可能在主线程和子线程之间进行切换(操作系统的线程切换是不受python虚拟机控制的,属于操作系统自身行为)”。python虚拟机的调度是一定是获得GIL基础之上的,而操作系统级的就不一定获得GIL了。

虽有操作系统会把未获得GIL的线程切换为活动线程,但是该线程发现自身并没有获得GIL会自动挂起。

只有当所有线程都完成了初始化操作,操作系统的线程调度和Python线程调度才会一致。那时,python的线程调度会迫使当前活动线程释放GIL,导致触发GIL中维护的Event内核对象,从而触发操作系统的线程调度。(在初始化完成之前,python线程调度和操作系统调度之间没有因果关系)

阻塞调度和线程销毁

在python中如果有raw_input等待输入的操作时将自身阻塞后,并将等待GIL线程唤醒,这种情况成为阻塞调度。

在线程通过阻塞调度切换时,python内部的时钟周期技术_Py_Ticker依然会被保持,不会被重置。

python的主线程销毁和子线程销毁是不同的,子线程只需要维护引用计数,而主线程还需要销毁运行环境。

用户级互斥和同步

上面讨论的GIL属于python内合计互斥,实现了保护内存的共享资源。而用户级互斥保护了用户程序中的共享资源。

python中提供了lock机制来实现线程之间的互斥。当线程通过lock.acquire获得lock之后,子线程会因为等待lock而挂起,直到主线程释放lock之后才会被Python的线程调度机制唤醒。

在线程执行过程中如果出现需要等待另一个lock资源的时候,需要将GIL转交给其他等待GIL的线程以避免死锁。

知识共享许可协议
本文 由 cococo点点 创作,采用 知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议进行许可。欢迎转载,请注明出处:
转载自:cococo点点 http://www.cnblogs.com/coder2012


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Python - 多线程、多进程
Python - 多线程、多进程
388 0
猪行天下之Python基础——9.2 Python多线程与多进程(中)(二)
内容简述: 1、threading模块详解 2、queue模块详解
34 0
猪行天下之Python基础——9.2 Python多线程与多进程(中)(一)
内容简述: 1、threading模块详解 2、queue模块详解
27 0
猪行天下之Python基础——9.1 Python多线程与多进程(上)(一)
内容简述: 线程与进程的相关概念  1、程序,进程,线程,多进程,多线程 2、线程的生命周期 3、并行与并发,同步与异步 4、线程同步安全 5、与锁有关的特殊情况:死锁,饥饿与活锁 6、守护线程 7、线程并发的经典问题:生产中与消费者问题 8、Python中的GIL锁 9、Python中对多线程与多进程的支持
40 0
猪行天下之Python基础——9.1 Python多线程与多进程(上)(二)
内容简述: 线程与进程的相关概念 1、程序,进程,线程,多进程,多线程 2、线程的生命周期 3、并行与并发,同步与异步 4、线程同步安全 5、与锁有关的特殊情况:死锁,饥饿与活锁 6、守护线程 7、线程并发的经典问题:生产中与消费者问题 8、Python中的GIL锁 9、Python中对多线程与多进程的支持
22 0
Python多线程与多进程浅析之二
Python 多线程 Step by Step Python 在 CPU 密集运算的场景,多个线程并不能提高太多性能,而对于 I/O 阻塞的场景,可以使得运行效率获得几倍的提高。我们接下来会详细的分析一下。
1836 0
1955
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载