Python多執行緒同步、互斥鎖、死鎖
- 2020 年 4 月 11 日
- 筆記
接著上篇多執行緒繼續講,上篇最後的多執行緒共享全局變數對變數的處理值出錯在本文中給出解決方案。
出現這個情況的原因是在python解釋器中GIL全局解釋器鎖。
GIL:全局解釋器鎖,每個執行緒在執行的過程都需要先獲取GIL,保證同一時刻只有一個執行緒而已執行程式碼
執行緒釋放GIL鎖的情況:在IO操作等呃能會引起阻塞的system call之前,可以暫時釋放GIL
但在執行完畢後,必須重新獲取GIL, Python3中使用計時器(執行時間打到閥值後,當前執行緒釋放GIL)
python使用多執行緒是並發 可以使用多執行緒利用多核的CPU資源
cpu密集型:也成為計算密集型,任務的特點是要進行大量的計算,消耗cpu資源,比如計算圓周率、對影片進行高清解碼等等
全靠cpu的運算能力 這個時候單執行緒快
io密集型:涉及到網路、磁碟IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成,因為 IO的速度遠遠低於CPU和記憶體的速度 這個時候多執行緒快。
那麼如何解決多執行緒共享全局變數數據錯誤的問題呢,引入鎖。
import threading a = 100 def func1(): global a for i in range(1000000): meta.acquire() # 上鎖 a += 1 meta.release() # 釋放鎖 print(a) def func2(): global a for i in range(1000000): meta.acquire() a += 1 meta.release() print(a) # 創建鎖 meta = threading.Lock() t1 = threading.Thread(target=func1) t2 = threading.Thread(target=func2) t1.start() t2.start() t1.join() t2.join() print(a)
至於鎖的原理在下方粗略的畫一張草圖以供參考
使用鎖讓每個執行緒有序的切換執行,不會出現數據混亂。
但是在使用鎖的時候要注意不要寫出死鎖程式碼,附死鎖程式碼參考,總結一句就是互相持有對方執行緒所需要的鎖,造成死鎖
import threading a = 100 def func1(): global a for i in range(1000000): meta_A.acquire() # 上鎖 meta_B.acquire() # 上多把鎖 產生了死鎖 看下面程式碼 print('-------------1') a += 1 meta_B.release() meta_A.release() # 釋放鎖 print(a) def func2(): global a for i in range(1000000): meta_B.acquire() meta_A.acquire() print('------------2') a += 1 meta_A.release() meta_B.release() print(a) # 創建鎖 meta_A = threading.Lock() meta_B = threading.Lock() t1 = threading.Thread(target=func1) t2 = threading.Thread(target=func2) t1.start() t2.start()
今天就寫到這裡,下一篇寫一下隊列

