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点点博客园博客,原文链接:http://www.cnblogs.com/coder2012/p/4567338.html,如需转载请自行联系原作者

相关文章
|
7天前
|
安全 Java 数据处理
Python网络编程基础(Socket编程)多线程/多进程服务器编程
【4月更文挑战第11天】在网络编程中,随着客户端数量的增加,服务器的处理能力成为了一个重要的考量因素。为了处理多个客户端的并发请求,我们通常需要采用多线程或多进程的方式。在本章中,我们将探讨多线程/多进程服务器编程的概念,并通过一个多线程服务器的示例来演示其实现。
|
17天前
|
算法 数据处理 Python
Python并发编程:解密异步IO与多线程
本文将深入探讨Python中的并发编程技术,重点介绍异步IO和多线程两种常见的并发模型。通过对比它们的特点、适用场景和实现方式,帮助读者更好地理解并发编程的核心概念,并掌握在不同场景下选择合适的并发模型的方法。
|
1月前
|
并行计算 安全 Unix
Python教程第8章 | 线程与进程
本章主要讲解了线程与进程的概念,多线程的运用以及Python进程的相关案例学习
36 0
|
1月前
|
分布式计算 并行计算 Java
浅析Python自带的线程池和进程池
浅析Python自带的线程池和进程池
73 0
|
1月前
|
Python
如何在Python中使用Semaphore来实现线程同步?
如何在Python中使用Semaphore来实现线程同步?
26 7
|
1月前
|
Python
在Python中,如何保证多个线程之间的同步?
在Python中,如何保证多个线程之间的同步?
22 4
|
24天前
|
安全 Python
Python中的并发编程:多线程与多进程技术探究
本文将深入探讨Python中的并发编程技术,重点介绍多线程和多进程两种并发处理方式的原理、应用场景及优缺点,并结合实例分析如何在Python中实现并发编程,以提高程序的性能和效率。
|
30天前
|
数据采集 存储 Java
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!
「多线程大杀器」Python并发编程利器:ThreadPoolExecutor,让你一次性轻松开启多个线程,秒杀大量任务!
|
1月前
|
安全 调度 Python
Python中如何实现多线程?请举例说明。
Python中如何实现多线程?请举例说明。
14 0
|
1月前
|
Java 调度 Python
深入解析 Python asyncio 库:如何使用线程池实现高效异步编程
深入解析 Python asyncio 库:如何使用线程池实现高效异步编程
43 0

热门文章

最新文章