您好,登錄后才能下訂單哦!
本文實例講述了Python多線程操作之互斥鎖、遞歸鎖、信號量、事件。分享給大家供大家參考,具體如下:
import time,threading x=6 def run1(): print("run1我拿到了數(shù)據(jù):",x) print("我現(xiàn)在還不想操作,先睡一下") time.sleep(3) print("再看一下數(shù)據(jù),穩(wěn)一穩(wěn)",x) def run2(): global x print("run2我拿到了數(shù)據(jù):", x) x=5 print(x) t1=threading.Thread(target=run1) t2=threading.Thread(target=run2) t1.start() t2.start() t1.join() t2.join()
使用互斥鎖來更改上段代碼
import time,threading x=6 def run1(): lock.acquire() global x print("run1我拿到了數(shù)據(jù),x=",x) print("我現(xiàn)在還不想操作,先睡一下") time.sleep(3) print("再看一下數(shù)據(jù),穩(wěn)一穩(wěn),x=",x) x+=1 print("run1操作完畢:x=",x) lock.release() def run2(): lock.acquire() global x print("run2我拿到了數(shù)據(jù):", x) x+=1 print("run2操作完畢:x=",x) lock.release() lock=threading.Lock()#生成一個鎖對象 t1=threading.Thread(target=run1) t2=threading.Thread(target=run2) t1.start() t2.start() start_time=time.time() t1.join() t2.join() print("最終的x=",x) print(time.time()-start_time)#3.0多說明,由于受到鎖的影響,run2要等待run1釋放lock,所以變成了串行
這種互斥鎖在操作系統(tǒng)中可以稱作“臨界區(qū)”,如果想了解更多:
https://baike.baidu.com/item/%E4%B8%B4%E7%95%8C%E5%8C%BA/8942134?fr=aladdin
【以過獨(dú)木橋為例】:橋只能容一個人通過,A只能看得到北邊橋上有沒有人,看不到南邊橋有沒有人,當(dāng)他看到北邊橋沒人就會過橋,等到他到橋中間才能看到南邊橋有沒有人,B情況相反:【于是當(dāng)兩個人一起過橋的時候就會發(fā)生死鎖】
import threading,time """ A只能看得到北邊橋上有沒有人,看不到南邊橋有沒有人, 當(dāng)他看到北邊橋沒人就會過橋,等到他到橋中間才能看到南邊橋有沒有人 """ def A(): lockNorth.acquire()#拿到北邊橋的鎖 print("A過橋北") time.sleep(3)#過橋中 lockSorth.acquire()#企圖過到南邊橋, print("A過橋南") time.sleep(3) # 過橋中 lockSorth.release() lockNorth.release() print("A過橋成功") """ B只能看得到南邊橋上有沒有人,看不到北邊橋有沒有人, 當(dāng)他看到南邊橋沒人就會過橋,等到他到橋中間才能看到北邊橋有沒有人 """ def B(): lockSorth.acquire() # 企圖過到南邊橋, print("B過橋南") time.sleep(3) # 過橋中 lockNorth.acquire() # 拿到北邊橋的鎖 print("B過橋北") time.sleep(3) # 過橋中 lockNorth.release() lockSorth.release() print("B過橋成功") lockNorth=threading.Lock() lockSorth=threading.Lock() tA=threading.Thread(target=A) tB=threading.Thread(target=B) tA.start() tB.start() tA.join() tB.join()
使用遞歸鎖來解決上面的死鎖問題:
import threading,time """ A只能看得到北邊橋上有沒有人,看不到南邊橋有沒有人, 當(dāng)他看到北邊橋沒人就會過橋,等到他到橋中間才能看到南邊橋有沒有人 """ def A(): lock.acquire()#拿到北邊橋的鎖 print("A過橋北") time.sleep(3)#過橋中 lock.acquire()#企圖過到南邊橋, print("A過橋南") time.sleep(3) # 過橋中 lock.release() lock.release() print("A過橋成功") """ B只能看得到南邊橋上有沒有人,看不到北邊橋有沒有人, 當(dāng)他看到南邊橋沒人就會過橋,等到他到橋中間才能看到北邊橋有沒有人 """ def B(): lock.acquire() # 拿南橋鎖, print("B過橋南") time.sleep(3) # 過橋中 lock.acquire() # 企圖拿北橋的鎖 print("B過橋北") time.sleep(3) # 過橋中 lock.release() lock.release() print("B過橋成功") lock=threading.RLock() tA=threading.Thread(target=A) tB=threading.Thread(target=B) tA.start() tB.start() tA.join() tB.join()
【由于本質(zhì)是一把鎖,A拿到鎖后,B要等待】
信號量可以限制進(jìn)入的線程的數(shù)量。
import threading,time def run(): s.acquire() print("hello") time.sleep(1.5) s.release() s=threading.BoundedSemaphore(3)#限制3個 threading_list=[] for i in range(12):#創(chuàng)建12個線程 obj=threading.Thread(target=run) obj.setDaemon(True) # 設(shè)置守護(hù)線程,避免干擾主線程運(yùn)行,并行等待 obj.start() for i in range(4): print("")#為了把結(jié)果分割,可以清楚看出分為了三組 time.sleep(1.5) #結(jié)果分為三組是因為運(yùn)行的太快了,三個線程裝入的時間差太小
import threading,time def read(): while True: if event.is_set(): print("事件已設(shè)置,我要讀了!!!!") time.sleep(1) else:#事件未設(shè)置 print("還沒寫好,我要等咯") event.wait()#那么就等著咯 #如果等到了 print("終于等到了!那么我又可以讀了") time.sleep(1) def write(): event.clear()#初始設(shè)空 while True: time.sleep(3)#寫 event.set()#設(shè)置事件,一旦set,那么讀者wait就有返回了,讀者可以繼續(xù)運(yùn)行了 print("write:寫好了") time.sleep(2)#等人讀 event.clear()#清除事件 event=threading.Event() #創(chuàng)建事件對象 t1=threading.Thread(target=write) t2=threading.Thread(target=read) t1.start() t2.start() t1.join() t2.join() """結(jié)果顯示:讀者確實一直在等待寫者寫好"""
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python進(jìn)程與線程操作技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門與進(jìn)階經(jīng)典教程》、《Python+MySQL數(shù)據(jù)庫程序設(shè)計入門教程》及《Python常見數(shù)據(jù)庫操作技巧匯總》
希望本文所述對大家Python程序設(shè)計有所幫助。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。