初淺聊聊 Python 的 GIL 及 Thread-safe
很喜歡與人討論程式語言的「特色」,因為這可以讓人知道你有多瞭解與喜愛你所用的程式語言。
雖然我已經十多年沒有認真寫過 Python
。頂多以前用 Python
寫過簡易的防毒軟體,中間幾次處理資料時用過 Python
,或處理一些鎖碎的自動化庶務,但不如各位有寫過規模型的產品或專案。可我對 Python 的瞭解,應該還可以和不少人討論。
今天來聊聊 Python GIL
因為近年 Python
的流行,愈來愈多人開始進入 Python
的世界,也發現不少 Pythonist (Python 開發工程師) 不瞭解 GIL
(甚至沒聽過),其實這也沒什麼大不了的,程式能動,好像也能跑出想要的結果。但若僅是如此,我覺得還談不上「瞭解 Python
」或「精通 Python
」。
不懂 GIL 很難說自己瞭解或精通 Python
有人覺得「平時根本用不到 GIL
,或反正無感」,但其實我們已經用了,只是你不知道。若不懂 GIL
,你無法瞭解或跟人談論 Lock
/ Process
/ Thread
/ Coroutine
,遇到稍微難解的問題,你會無法克服;遇到效能問題,你會覺得 Python
就是慢。而往往是這些知識,才能讓我們變成「解決問題的人」,而不是「換掉 Python
的人」。
甚至可能有人會覺得「反正因為 GIL
,所以 Python
寫出的程式會是 Thread-safe
的」。其實不然,GIL
並不能保證 Python
寫出來的程式是 Thread-safe
。
來測試我們對於 Python Thread-safe 的認知
你覺得這行程式碼是 Thread-safe
嗎?
i = i + 1
這行程式碼,在 Python
的世界裡,並不是 Thread-safe
,意謂著在 multi-threading 下,這段程式碼的執行結果可能不是你想要的。
以下這些範例也都不是 Thread-safe
,
List[i] = List[j]
List[i] = List[i] + 1
List.append(List[-1])
雖然 GIL
可以用於內部確保在 Python
VM 中同時僅運行一個 Thread,但通常,Python
要在 Threads 間切換時,只能在 Bytecode instructions 間,而不是 Python
程式碼。
所以,GIL
保證的 Thread-safe
是 Bytecode 而不是 Python
Code。Python
Code 要編成 Bytecodes 才會在 Python
VM 上運行。
GIL 保證的 Thread 安全是在 Bytecode 層不是 Python Code 層
瞭解 GIL
後,你就可以比較容易利用 Lock
/ Process
/ Thread
/ Coroutine
寫出高效能的程式,去處理高效能網站或巨量資料的應用等。
額外:從 Python 小談 Go
Python
與 Go
本身內建 unittest,不像 PHP
我還要額外安裝 PHPUnit 才能有比較好的測試環境,這對我是一大利多。
另外 Python
AsyncIO 是 N:1 model,Go
是 M:N model,這先瞭解也會比較好。
還有 Go
可以利用 race 協助偵測 Race Condition 的潛在問題,這點我在 Python
似乎還沒找到比較好的方法。