看板 Marginalman
全局鎖(global interpreter lock,GIL) 討論python的thread 我們就不得不提到GIL 這邊必須先聲明 GIL不是python的特性 這是cpython的產物 cpython是python的直譯器 假如您想避開GIL 您可以考慮其他直譯器 諸如jpython 但cpython是大多數情況的默認環境 所以大多數python使用者還是得面對GIL GIL創立的目的是為了解決多線程的安全問題 這邊要先介紹cpython的記憶體管理機制 cpython有一種管理方式叫引用記數 cpython的object的struct裡面有個東西叫ob_refcnt 當你創建或引用變數時 ob_refcnt會+1 反之-1 當我們使用多線程時 線程會共用記憶體 這意味著線程會共用全局變數 當不同線程同時修改同個變數的引用記數 這就可能導致內存洩漏或內存提前被釋放 總之 cpython考慮線程安全 才會引進GIL GIL的具體運作方式 線程執行前 必須取得GIL 取得後才能開始執行任務 如果線程進入IO任務或執行超過一定時間(通常15毫秒)或執行完成 釋放GIL 所以一個線程會經歷三個步驟: 1.爭取GIL 2.執行任務 3.釋放GIL 因為只有一個GIL 所以一段時間內只會有一個線程運行 假設是多核心的情況 其他進程本來能在其他核心運行 因為GIL的緣故 其他核心只能在一旁閒置 所以python的多線程才會被說實際是單線程 從執行的效率來說 有GIL的多線程甚至不如單線程 因為每當GIL釋放 系統需要執行線程切換 線程切換是保存線程的狀態 並載入下一個執行的線程 再者 GIL釋放時 線程會被喚醒競爭GIL 當GIL頻繁被釋出 上述行為重複執行 這耗費了大量的CPU資源 反觀單線程就不需要執行上述行為 所以在CPU密集型任務 單線程優於多線程 PY: import time def countdown(n): while (n > 0): n = n - 1 start = time.time() countdown(100000000) end = time.time() print('總時間:', end - start) result: 總時間: 2.3528549671173096 py: import time import threading def countdown(n): while (n > 0): n = n - 1 t1 = threading.Thread(target=countdown, args=(100000000/2,)) t2 = threading.Thread(target=countdown, args=(100000000/2,)) start = time.time() t1.start() t2.start() t1.join() t2.join() end = time.time() print('總時間:', end - start) result: 總時間: 2.818242073059082 上述結果可以證明在cpu密集型任務 單線程優於多線程 先這樣 後面應該會寫gil爭搶的可能問題 gil實際並沒有線程安全 怎解決gil問題ㄅ 累了 剩下明天再寫 參考資料: https://wiki.python.org/moin/GlobalInterpreterLock https://yhtechnote.com/global-interpreter-lock/ -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.136.174.252 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Marginalman/M.1727708059.A.EA7.html
handfox: 大師 09/30 22:54
sustainer123: 好久不見 手狐你是112大老 09/30 22:55
HGK: 證明了 intel核心臭打遊戲強 09/30 22:56
Lilchicken: 別打了 我腦子要炸了 09/30 22:57
Kroner: 甘露糖功效 09/30 22:57
cities516: 什麼! 09/30 22:57
sustainer123: 懶人包:python請用multiprocessing 09/30 22:58
enmeitiryous: 跟user level 和kernel level 的thread 的概念很像 09/30 23:01
Kroner: 魚油推薦 09/30 23:01
enmeitiryous: 嗎 09/30 23:01
DJYOSHITAKA: 大師 09/30 23:09
sustainer123: 概念上我感覺類似 但具體上可能要再研究 09/30 23:12
Kroner: 09/30 23:12
enmeitiryous: 想起來了 多對一模式 多個使用者空間thread 其實 09/30 23:19
enmeitiryous: 對應同個kernel thread 09/30 23:19
sustainer123: 大師 我os還沒讀完 研究中 09/30 23:22
Chricey: 葉黃素 09/30 23:22