您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)Python多線程的原理是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
Python主要應(yīng)用于:1、Web開發(fā);2、數(shù)據(jù)科學(xué)研究;3、網(wǎng)絡(luò)爬蟲;4、嵌入式應(yīng)用開發(fā);5、游戲開發(fā);6、桌面應(yīng)用開發(fā)。
創(chuàng)建并啟動一個線程
import threading def runtask(name): print("%s線程已啟動"%name) t = threading.Thread(target=runtask,args=("task1",)) # args因為是一個元組,所以必須這樣寫,否則運(yùn)行將報錯 t.start()
join
等待當(dāng)前線程執(zhí)行完畢
import threading import time def runtask(name): print("%s線程已啟動"%name) time.sleep(2) t = threading.Thread(target=runtask,args=("task1",)) t.start() t.join() print("abc") # 過了2s才會打印,若無等待將看不到等待2s的效果
setDaemon(True)
將線程設(shè)置為守護(hù)線程。若設(shè)置為守護(hù)線程,主線程結(jié)束后,子線程也將結(jié)束,并且主線程不會理會子線程是否結(jié)束,主線程不會等待子線程結(jié)束完后才結(jié)束。若沒有設(shè)置為守護(hù)線程,主線程會等待子線程結(jié)束后才會結(jié)束。
active_count
程序的線程數(shù)量,數(shù)量=主線程+子線程數(shù)量
Lock(互斥鎖)
Python編程中,引入了對象互斥鎖的概念,來保證共享數(shù)據(jù)操作的完整性。每個對象都對應(yīng)于一個可稱為” 互斥鎖” 的標(biāo)記,這個標(biāo)記用來保證在任一時刻,只能有一個線程訪問該對象。在Python中我們使用threading模塊提供的Lock類。
import threading,time def runtask(name): global count time.sleep(1) lock.acquire() # 獲取鎖資源,并返回是否獲取成功 count+=1 print(name,count) lock.release() # 釋放資源 count = 0 lock = threading.Lock() # 互斥鎖 for index in range(50): t = threading.Thread(target=runtask,args=("thread%d"%index,)) t.start()
上面這段代碼如果沒有加上互斥鎖,在Python2.x中執(zhí)行的結(jié)果將會是亂的。在Python3.x中執(zhí)行卻總是正確的,似乎是自動為其加了鎖
RLock(遞歸鎖,可重入鎖)
當(dāng)一個線程中遇到鎖嵌套情況該怎么辦,又會遇到什么情況?
def run1(): global count1 lock.acquire() count1 += 1 lock.release() return count1 def run2(): global count2 lock.acquire() count2 += 1 lock.release() return count2 def runtask(): lock.acquire() r1 = run1() print("="*30) r2 = run2() lock.release() print(r1,r2) count1,count2 = 0,0 lock = threading.Lock() for index in range(50): t = threading.Thread(target=runtask,) t.start()
這是一個很簡單的線程鎖死案例,程序?qū)⒈豢ㄋ溃V共粍?。為了解決這一情況,Python提供了遞歸鎖RLock(可重入鎖)。這個RLock內(nèi)部維護(hù)著一個Lock和一個counter變量,counter記錄了acquire的次數(shù),從而使得資源可以被多次require。直到一個線程所有的acquire都被release,其他的線程才能獲得資源。上面的代碼只需做一些小小的改動
lock = threading.Lock()
修改為:
lock = threading.RLock()
那么程序?qū)⒉粫l(fā)生死鎖情況。
最大可執(zhí)行線程
threading.BoundedSemaphore(5)
設(shè)置可同時執(zhí)行的最大線程數(shù)為5個,后面的線程需排隊等待前面的線程執(zhí)行完畢
import time,threading def runtask(name): global num semaphore.acquire() time.sleep(1) num += 1 semaphore.release() print(name,num) num = 0 semaphore = threading.BoundedSemaphore(5) for index in range(50): t = threading.Thread(target=runtask,args=("線程%s"%index,)) t.start()
執(zhí)行效果:
可以看出上面的程序是每次只有5個線程在同時運(yùn)行,其他線程需等待前面的線程執(zhí)行完畢,這就是最大可執(zhí)行線程。
Event
Python提供了Event對象用于線程間通信,它是由線程設(shè)置的信號標(biāo)志,如果信號標(biāo)志位為假,則線程等待直到信號被其他線程設(shè)置成真。Event中提供了四個重要的方法來滿足基本的需求。
- clear:清除標(biāo)記
- set:設(shè)置標(biāo)記
- is_set:是否被標(biāo)記
- wait:等待被標(biāo)記
代碼示例:
import threading,time def lighter(): num = 0 event.set() # 設(shè)置標(biāo)記 while True: if num >= 5 and num < 10: event.clear() # 清除標(biāo)記 print("紅燈亮起,車輛禁止通行") if num >= 10: event.set() # 設(shè)置標(biāo)記 print("綠燈亮起,車輛可以通行") num = 0 num += 1 time.sleep(1) def car(): while True: if event.is_set(): print("車輛正在跑...") else: print("車輛停下了") event.wait() time.sleep(1) event = threading.Event() t1 = threading.Thread(target=lighter,) t2 = threading.Thread(target=car,) t1.start() t2.start()
這是一個簡單的紅燈停綠燈行案例。初始設(shè)置為綠燈并標(biāo)記,車輛看到標(biāo)記后通行,當(dāng)紅燈亮起的時候取消標(biāo)記,車輛看到?jīng)]有標(biāo)記時停下,等待標(biāo)記。
Queue隊列
使任務(wù)按照某一種特定順序有條不紊的進(jìn)行。下面介紹幾種常用的隊列:
- queue.Queue()
:先進(jìn)先出
- queue.LifoQueue()
:先進(jìn)后出
- queue.PriorityQueue
:優(yōu)先級隊列,優(yōu)先級的值越小,越先執(zhí)行
下面介紹幾種常用的方法:
- get()
:獲取item,如果隊列已經(jīng)取空將會卡住??稍O(shè)置timeout參數(shù),給定一個超時的值,或者設(shè)置參數(shù)block=False,隊列空直接拋異常
- get_nowait()
:b獲取item。如果隊列取空了,將會直接拋異常
- put()
:放入隊列
- empty()
:隊列是否為空
- qsize()
:獲取隊列的item數(shù)量
上述就是小編為大家分享的Python多線程的原理是什么了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(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)容。