接着上篇多線程繼續講,上篇最後的多線程共享全局變量對變量的處理值出錯在本文中給出解決方案。python
出現這個狀況的緣由是在python解釋器中GIL全局解釋器鎖。網絡
GIL:全局解釋器鎖,每一個線程在執行的過程都須要先獲取GIL,保證同一時刻只有一個線程而已執行代碼多線程
線程釋放GIL鎖的狀況:在IO操做等呃能會引發阻塞的system call以前,能夠暫時釋放GIL併發
但在執行完畢後,必須從新獲取GIL, Python3中使用計時器(執行時間打到閥值後,當前線程釋放GIL)ui
python使用多線程是併發 能夠使用多線程利用多核的CPU資源spa
cpu密集型:也成爲計算密集型,任務的特色是要進行大量的計算,消耗cpu資源,好比計算圓周率、對視頻進行高清解碼等等線程
全靠cpu的運算能力 這個時候單線程快code
io密集型:涉及到網絡、磁盤IO的任務都是IO密集型任務,這類任務的特色是CPU消耗不多,任務的大部分時間都在等待IO操做完成,由於 IO的速度遠遠低於CPU和內存的速度 這個時候多線程快。視頻
那麼如何解決多線程共享全局變量數據錯誤的問題呢,引入鎖。blog
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()
今天就寫到這裏,下一篇寫一下隊列