设为首页 收藏本站
查看: 1008|回复: 0

[经验分享] python 多线程

[复制链接]

尚未签到

发表于 2015-11-29 11:00:20 | 显示全部楼层 |阅读模式
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的线程以避免死锁。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-144855-1-1.html 上篇帖子: Python程序员常用的IDE和其它开发工具 下篇帖子: 用pygame学习初级python(二) 15.5.11
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表