有時候我們會聽到python有一個叫做GIL鎖的東西,這個東西是做什麼的? 什麼又是執行緒安全?下文會嘗試回答這些問題。
什麼是執行緒
執行緒(thread)是電腦用來分配任務到資源的最小單位,在這邊我們常會聽到以下的名詞:程式(program)、 行程(process)以及執行緒(thread),這三者的關係如下:
當電腦執行一個程式時,便會建立一個行程,舉例來說,當電腦執行一個記事本程式,便會產生一個行程以及分配相應的資源來執行它,但要注意的是,一個程式可以跟好幾個行程有關,譬如說我們現在打開的多個記事本,那就會有多個行程對應到同一個記事本程式。
而另一方面,在每一個行程下面可以有一個或是多個執行緒來完成行程所需要的任務,以記事本的例子為例,但我們執行記事本程式時,它可能有一個執行緒是負責處理使用者的輸入,而另一個執行緒是負責處理將文字顯示在螢幕上。
什麼是執行緒安全
所謂的執行緒安全便是指當多個執行緒調用同一個共享變量時,不會造成變量資料的錯誤使用。舉例來說,現在我們有一個資料庫,兩個執行緒同時執行查詢並加入資料的功能,假設現在兩個執行緒都在尋找a,而目前資料庫並沒有a,則兩個執行緒便同時接收到沒有a的查找結果,並同時加入a,這便會導致程式執行並不正確。
GIL鎖
為了使程式盡可能避免執行緒不安全的情況,python語言加入了全局鎖(GIL)的機制,我們可以想像為,python限制在每一個時刻只能執行一個執行緒,但這樣就可以完全避免多執行緒產生的潛在問題了嗎? 讓我們考慮以下的例子:
GIL下的執行緒不安全與原子操作
假設我們像在有一個函式,它會跑一個迴圈,在每一次遞迴,會對x這個變量進行x +=1 與x-=1的兩個操作,我們開了兩個執行緒去執行它,照理來說,x經過+1與-1後,最後變量的值應該為0,但是如果參考這個連結的代碼,它執行的結果很有可能不是0,其原理在於x+=1這個操作是兩步操作的結合:
第一步:y=x+1
第二步:x=y
因此在執行第一步的時候,有可能全局鎖就釋放,並將執行權力交給另一個執行緒,這便可能造成執行結果並不盡如人意。 更詳細的說明可以參考連結。
原子操作
這樣我們就可以連結到原子操作這個概念,原子操作是指那些不會被執行緒調度所中斷的指令,像是剛才+=1這種操作便不是原子操作。
列表的執行緒安全
那如果我們想要保證一串資料是執行緒安全的話,我們應該怎麼做?我們可以選擇不用列表(list)來儲存這一串資料,python的標準庫裡面內建了queue這個模組,這個模組裡面可以建構queue這個資料結構,裡面的基本操作便是原子操作,我們可以利用queue這個資料結構來確保執行緒安全。
I am just writing to make you understand what a perfect experience my wife’s girl obtained using your webblog. She noticed so many pieces, which included what it is like to possess an excellent helping spirit to let others with no trouble learn about specific specialized things. You truly surpassed readers’ expected results. Thank you for providing these priceless, trusted, informative as well as fun tips about this topic to Lizeth.