python 多線程鎖機制

來源:互聯網
上載者:User

標籤:append   線程   src   導致   線程鎖   tool   oba   threading   結果   

GIL(全域解譯器鎖)

GIL並不是Python的特性,它是在實現Python解析器(CPython)時所引入的一個概念,是為了實現不同線程對共用資源訪問的互斥,才引入了GIL

在Cpython解譯器中,同一個進程下開啟的多線程,同一時刻只能有一個線程執行,無法利用多核優勢

python對於計算密集型的任務開多線程的效率甚至不如串列(沒有大量切換),但是,對於IO密集型的任務效率還是有顯著提升的。

GIL原理圖

 

計算密集型:結果肯定是100,因為每一次start結果就已經出來了,所以第二個線程肯定是通過調用第一個線程的count值進行計算的

 1 def sub(): 2     global count 3  4     ‘‘‘線程的公用資料  下‘‘‘ 5     temp=count 6     count=temp+1 7     ‘‘‘線程的公用資料  上‘‘‘ 8  9     time.sleep(2)10 count=011 12 l=[]13 for i in range(100):14     t=threading.Thread(target=sub,args=())15     t.start()  #每一次線程啟用,申請一次gillock16     l.append(t)17 for t in l:18     t.join()19 print(count)

 

io密集型:當第一個線程開始start的時候,由於sleep了0.001秒,這0.001秒對於人而言很短,但是對於cpu而言,這0.001秒已經做了很多的事情了,在這裡cpu做的事情就是或許已經start了100個線程,所以導致大多數的線程調用的count值還是0,即temp=0,只有少數的線程完成了count=temp+1的操作,所以輸出的count結果不確定,可能是7、8、9,也可能是10幾。

 1 def sub(): 2     global count 3  4     ‘‘‘線程的公用資料  下‘‘‘ 5     temp=count 6     time.sleep(0.001)    #大量的io操作 7     count=temp+1 8     ‘‘‘線程的公用資料  上‘‘‘ 9 10     time.sleep(2)11 count=012 13 l=[]14 for i in range(100):15     t=threading.Thread(target=sub,args=())16     t.start()17     l.append(t)18 for t in l:19     t.join()20 print(count)

 

注意以下的鎖都是多線程提供的鎖機制,與python解譯器引入的gil概念無關

互斥鎖(同步鎖)

互斥鎖是用來解決上述的io密集型情境產生的計算錯誤,即目的是為了保護共用的資料,同一時間只能有一個線程來修改共用的資料。

 1 def sub(): 2     global count 3     lock.acquire()  #上鎖,第一個線程如果申請到鎖,會在執行公用資料的過程中持續阻塞後續線程 4                     #即後續第二個或其他線程依次來了發現已經被上鎖,只能等待第一個線程釋放鎖 5                     #當第一個線程將鎖釋放,後續的線程會進行爭搶 6  7     ‘‘‘線程的公用資料  下‘‘‘ 8     temp=count 9     time.sleep(0.001)10     count=temp+111     ‘‘‘線程的公用資料  上‘‘‘12 13     lock.release()  #釋放鎖14     time.sleep(2)15 count=016 17 l=[]18 lock=threading.Lock()   #將鎖內的代碼序列化19 for i in range(100):20     t=threading.Thread(target=sub,args=())21     t.start()22     l.append(t)23 for t in l:24     t.join()25 print(count)

 

死結

保護不同的資料就應該加不同的鎖。

所以當有多個互斥鎖存在的時候,可能會導致死結,死結原理如下:

 1 import threading 2 import time 3 def foo(): 4     lockA.acquire() 5     print(‘func foo ClockA lock‘) 6     lockB.acquire() 7     print(‘func foo ClockB lock‘) 8     lockB.release() 9     lockA.release()10 11 def bar():12 13     lockB.acquire()14     print(‘func bar ClockB lock‘)15     time.sleep(2)  # 類比io或者其他動作,第一個線程執行到這,在這個時候,lockA會被第二個進程佔用16                    # 所以第一個進程無法進行後續操作,只能等待lockA鎖的釋放17     lockA.acquire()18     print(‘func bar ClockA lock‘)19     lockB.release()20     lockA.release()21 22 def run():23     foo()24     bar()25 26 lockA=threading.Lock()27 lockB=threading.Lock()28 for i in range(10):29     t=threading.Thread(target=run,args=())30     t.start()31 32 輸出結果:只有四行,因為產生了死結阻斷了33 func foo ClockA lock34 func foo ClockB lock35 func bar ClockB lock36 func foo ClockA lock

 

 

遞迴鎖(重要)

解決死結

 1 import threading 2 import time 3 def foo(): 4     rlock.acquire() 5     print(‘func foo ClockA lock‘) 6     rlock.acquire() 7     print(‘func foo ClockB lock‘) 8     rlock.release() 9     rlock.release()10 11 def bar():12     rlock.acquire()13     print(‘func bar ClockB lock‘)14     time.sleep(2)15     rlock.acquire()16     print(‘func bar ClockA lock‘)17     rlock.release()18     rlock.release()19 20 21 def run():22     foo()23     bar()24 25 rlock=threading.RLock() #RLock本身有一個計數器,如果碰到acquire,那麼計數器+126                         #如果計數器大於0,那麼其他線程無法查收,如果碰到release,計數器-127 28 for i in range(10):29     t=threading.Thread(target=run,args=())30     t.start()

 

 

Semaphore(訊號量)

實際上也是一種鎖,該鎖用於限制線程的並發量

以下代碼在sleep兩秒後會列印出100個ok

1 import threading2 import time3 def foo():4     time.sleep(2)5     print(‘ok‘)6 7 for i in range(100):8     t=threading.Thread(target=foo,args=())9     t.start()

 

每2秒列印5次ok

 1 import threading 2 import time 3 sem=threading.Semaphore(5) 4 def foo(): 5     sem.acquire() 6     time.sleep(2) 7     print(‘ok‘) 8     sem.release() 9 10 for i in range(100):11     t=threading.Thread(target=foo,args=())12     t.start()

 

python 多線程鎖機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.