标签:字节码 虚拟 同事 gil === 并发 开始 ++ 编译
python 代码的执行由python虚拟机来控制,虚拟机访问由GIL控制,保证其同一时刻只有一条线程运行。
虽然python能运行多线程,但是因为GIL所以同一时刻只有一条线程在python解释器运行。
多线程下python虚拟机按以下方式执行:
1. 设置GIL
2. 切换到一条线程去运行
3. 运行:
a. 执行python2虚拟机运行1000字节指令 或者 执行python3虚拟机运行时间15ms字节
b. 线程主动让出控制(遭遇sleep或者IO操作也将触发)
4. 把线程设置为睡眠状态(等待状态)
5. 释放GIL
6. 再次重复上述操作
线程何时切换?
==========================================================
(1)一个线程无论何时开始睡眠或等待网络 I/O,其他线程总有机会获取 GIL 执行 Python 代码。这是协同式多任务处理。CPython 也还有抢占式多任务处理。如果一个线程不间断地在 Python 2 中运行 1000 字节码指令,或者不间断地在 Python 3 运行15 毫秒,那么它便会放弃 GIL,而其他线程可以运行。把这想象成有多个线程但只有一个 CPU 时的时间片可用。
(2)当执行C/C++代码时候,直到C函数执行完毕,才让出GIL。
让我们回顾下 Python 是如何运行的。你的程序分两个阶段运行。首先,Python文本被编译成一个名为字节码的简单二进制格式。第二,Python解释器的主回路,一个名叫 pyeval_evalframeex() 的函数,流畅地读取字节码,逐个执行其中的指令。
当解释器通过字节码时,它会定期放弃GIL,而不需要经过正在执行代码的线程允许,这样其他线程便能运行:默认情况下,检测间隔是1000 字节码。所有线程都运行相同的代码,并以相同的方式定期从他们的锁中抽出。在 Python 3 GIL 的实施更加复杂,检测间隔不是一个固定数目的字节码,而是15 毫秒。然而,对于你的代码,这些差异并不显著。
当一项任务比如网络 I/O启动,而在长的或不确定的时间,没有运行任何 Python 代码的需要,一个线程便会让出GIL,从而其他线程可以获取 GIL 而运行 Python。
这种礼貌行为称为协同式多任务处理,它允许并发;多个线程同时等待不同事件。多个线程在同一时刻只能有一个执行 Python ,但一旦线程开始连接,它就会放弃 GIL ,这样其他线程就可以运行。这意味着多个线程可以并发等待套接字连接,这是一件好事。在同样的时间内它们可以做更多的工作。
标签:字节码 虚拟 同事 gil === 并发 开始 ++ 编译
原文地址:https://www.cnblogs.com/7134g/p/11516880.html