接着上篇多線程繼續講,上篇最后的多線程共享全局變量對變量的處理值出錯在本文中給出解決方案。
出現這個情況的原因是在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()
今天就寫到這里,下一篇寫一下隊列