python 代碼的執(zhí)行由python虛擬機來控制,虛擬機訪問由GIL控制,保證其同一時刻只有一條線程運行。
雖然python能運行多線程,但是因為GIL所以同一時刻只有一條線程在python解釋器運行。
?
多線程下python虛擬機按以下方式執(zhí)行:
1. 設置GIL
2. 切換到一條線程去運行
3. 運行:
a. 執(zhí)行python2虛擬機運行1000字節(jié)指令? ? 或者? ? 執(zhí)行python3虛擬機運行時間15ms字節(jié)
b. 線程主動讓出控制(遭遇sleep或者IO操作也將觸發(fā))
4. 把線程設置為睡眠狀態(tài)(等待狀態(tài))
5. 釋放GIL
6. 再次重復上述操作
?
線程何時切換?
==========================================================
(1)一個線程無論何時開始睡眠或等待網絡 I/O,其他線程總有機會獲取 GIL 執(zhí)行 Python 代碼。這是協(xié)同式多任務處理。CPython 也還有搶占式多任務處理。如果一個線程不間斷地在 Python 2 中運行 1000 字節(jié)碼指令,或者不間斷地在 Python 3 運行15 毫秒,那么它便會放棄 GIL,而其他線程可以運行。把這想象成有多個線程但只有一個 CPU 時的時間片可用。
(2)當執(zhí)行C/C++代碼時候,直到C函數執(zhí)行完畢,才讓出GIL。
?
讓我們回顧下 Python 是如何運行的。你的程序分兩個階段運行。首先,Python文本被編譯成一個名為字節(jié)碼的簡單二進制格式。第二,Python解釋器的主回路,一個名叫 pyeval_evalframeex() 的函數,流暢地讀取字節(jié)碼,逐個執(zhí)行其中的指令。
搶占式多任務處理
當解釋器通過字節(jié)碼時,它會定期放棄GIL,而不需要經過正在執(zhí)行代碼的線程允許,這樣其他線程便能運行:默認情況下,檢測間隔是1000 字節(jié)碼。所有線程都運行相同的代碼,并以相同的方式定期從他們的鎖中抽出。在 Python 3 GIL 的實施更加復雜,檢測間隔不是一個固定數目的字節(jié)碼,而是15 毫秒。然而,對于你的代碼,這些差異并不顯著。
協(xié)同式多任務處理
當一項任務比如網絡 I/O啟動,而在長的或不確定的時間,沒有運行任何 Python 代碼的需要,一個線程便會讓出GIL,從而其他線程可以獲取 GIL 而運行 Python。
這種禮貌行為稱為協(xié)同式多任務處理,它允許并發(fā);多個線程同時等待不同事件。多個線程在同一時刻只能有一個執(zhí)行 Python ,但一旦線程開始連接,它就會放棄 GIL ,這樣其他線程就可以運行。這意味著多個線程可以并發(fā)等待套接字連接,這是一件好事。在同樣的時間內它們可以做更多的工作。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
