執行緒,執行緒安全與python的GIL鎖

2022-03-23 08:17:22 字數 3351 閱讀 1823

今天看到一篇文章,講述的是幾個提公升python效能的專案:傳送門

在看的過程中,接觸到乙個名詞,乙個從學python開始就一直看到,但是從來都是一知半解的名詞,心裡不開心,必須把它搞明白,對了,這個詞就是 gil。網上搜尋了一些資料,粗淺的理解了什麼是gil,自己感覺學習的過程比較好,感覺略有收穫,老規矩,為了鞏固知識,自己整片文章出來寫一寫,其實好多文章已經寫的很完善了,所以這篇隨筆,只做知識鞏固,如有雷同,請各位原創作者原諒,小菜鳥一枚,如果**寫的有問題,還請各位前輩不吝指正。

一句話:解決多執行緒之間資料完整性和狀態同步的最簡單方法自然就是加鎖。

首先,gil的全名,global interpreter lock,鑑於英文水平,不做名詞翻譯,以免誤導。大體解釋一下,這個鎖就是用來為了解決cpython多執行緒中線程不安全問題引入的乙個全域性排它鎖,它的作用就是在多執行緒情況下,保護共享資源,為了不讓多個執行緒同時操作共享資源,導致不可預期的結果而加上的鎖,在乙個執行緒操作共享資源時,其他執行緒請求該資源,只能等待gil解鎖。這個設定在cpython剛引入多執行緒概念的時候就有了,然後後續的各種包和元件開發都不可避免的受到了gil的影響,所以有人會說,python在多執行緒處理的時候很慢。python gil實現方式類似於如下偽**:

if

__name__ == '

__main__':

gil鎖開始運作

主線程做操作

主線程完成操作

gil鎖釋放資源

所以多執行緒共同操作共享資源的時候,有乙個執行緒競得了資源,它就被gil鎖保護起來,其他執行緒只能是在那裡等著,但是這個時候,執行緒的休眠喚醒,全部會消耗cpu資源,所以嘞,就會慢。

看到這個時候,我又發現了乙個名詞:執行緒安全。這個名詞,也是那種特別熟悉,但就是無法清晰的說出它是啥的概念。查了資料,在這記一下:

執行緒安全就是多執行緒訪問時,採用了加鎖機制,當乙個執行緒訪問該類的某個資料時,進行保護,其他執行緒不能進行訪問直到該執行緒讀取完,其他執行緒才可使用。不會出現資料不一致或者資料汙染。 執行緒不安全就是不提供資料訪問保護,有可能出現多個執行緒先後更改資料造成所得到的資料是髒資料。

順序執行的單執行緒(single_thread.py)

#! /usr/bin/python

from threading import

thread

import

time

defmy_counter():

i =0

for _ in range(100000000):

i = i + 1

return

true

defmain():

thread_array ={}

start_time =time.time()

for tid in range(2):

t = thread(target=my_counter)

t.start()

t.join()

end_time =time.time()

print("

total time: {}

".format(end_time -start_time))

if__name__ == '

__main__':

main()

同時執行的兩個併發執行緒(multi_thread.py)

#! /usr/bin/python

from threading import

thread

import

time

defmy_counter():

i =0

for _ in range(100000000):

i = i + 1

return

true

defmain():

thread_array ={}

start_time =time.time()

for tid in range(2):

t = thread(target=my_counter)

t.start()

thread_array[tid] =t

for i in range(2):

thread_array[i].join()

end_time =time.time()

print("

total time: {}

".format(end_time -start_time))

if__name__ == '

__main__':

main()

最終結果如下:

過程證明了因為gil的存在,導致python在使用多執行緒的時候反而不如順序執行快。

此處我又溫習了一下python執行緒:

執行緒的順序執行還是多執行緒併發,取決於join函式的位置。join函式的作用是等待當前執行緒結束,所以每乙個執行緒建立之後,呼叫start函式,這是在後面跟上該執行緒的join函式,那麼就是順序執行,如果多個執行緒先完成建立和start,最後加上join函式,那麼就變成了多執行緒併發。

這就是今天的學習內容,其實所有知識網上都能找到,更想分享的是一種學習的方法,一種本身很不推薦的學習方法,那就是類似於探索性測試的學習,啥不懂就去看啥,有些時候,我們學習東西確實不能非要究其內在,軟體行業的學習本身在非本行人事看來就特別神奇且枯燥,所以最初的學習,我們需要整個圖形介面,讓我們學到的東西有了成就感,如果上來先去研究機器碼,那麼沒幾個人願意學下去,但是不管怎樣,既然走上了軟體行業的道路,這種探索性,打破砂鍋問到底的學習,在我的感覺裡應該是必經之路,也就是所謂的底層研究。以安卓開發舉例,如果做安卓開發的,雖然能寫出很漂亮的介面,解決所有的bug,如果不了解安卓系統linux層的知識,在我的眼裡,從未把這種研發看做大牛。當然我並不覺得不了解linux底層的安卓研發可以解決任何bug

當下的軟體行業進入了乙個神奇的階段,我已經聽過無數遍的理論,培訓機構出來就能賺錢,大學讀著沒用,在這裡不討論教育體制問題,從個人情感上,我覺得大學教育雖然沒有教給學生直接找工作的技能,但是給了所有學生乙個能夠了解基礎知識的園地,換而言之,作為行業的一員,總應該有將行業發展起來的覺悟,行業內整體風氣,缺乏靜下心來的沉澱。在大談敏捷,行為驅動,機器學習的同時,自己需要靜下心來回頭看看,基礎已然不牢,再走下去是否有些危險。是不是學習軟體技術,就是為了獲取網際網路行業那虛高的工資,是否已經侷限於第三方框架,一旦框架出現問題,只能打給客服而束手無策,是否有過沒有做任何嘗試就將bug歸咎於安卓系統,阿里中介軟體等等,是不是舊技術還沒用明白,為了新技術就可以不再去研究。

還是小菜鳥,在此大談行業發展難免有些放肆,如有不對的地方,還請各位前輩不吝指正

執行緒安全與非執行緒安全的區別

執行緒安全 是多執行緒訪問時,採用加鎖機制,當乙個執行緒訪問該類的某個資料時,進行保護,其他執行緒不能進行訪問直到該執行緒讀取完,其他執行緒才可使用。不會出現資料不一致或者資料汙染。非執行緒安全 是多執行緒訪問時,不提供資料訪問保護,有可能出現多個執行緒先後更改資料造成所得到的資料是髒資料。所得資料...

執行緒安全與執行緒同步

執行緒安全 可重入函式 執行緒之間共享全域性資料段 靜態資料,引起非執行緒安全。執行緒安全可以通過執行緒同步對臨界資源訪問進行控制來實現。有些系統呼叫或者庫函式的實現時發生不安全現象,在多執行緒環境下就需要使用這些函式的安全版本,即可重入函式。例如 字串分割函式 普通版本 char strtok c...

執行緒安全與同步執行緒

資料有負數,相同的情況 比如在進行搶票的時候。可能會出現在第資料不準確的現象 public class unsafe implements runnable public static void test catch interruptedexception e system.out.println...