1. 程式人生 > 程式設計 >Python多執行緒threading join和守護執行緒setDeamon原理詳解

Python多執行緒threading join和守護執行緒setDeamon原理詳解

同一程序下的多個執行緒共享記憶體資料,多個執行緒之間沒有主次關係,相互之間可以操作;cpu執行的都是執行緒,預設程式會開一個主執行緒;程序是程式以及和程式相關資源的集合;某些場景下我們可以使用多執行緒來達到提高程式執行效率的目的,下面就多執行緒的一些基礎知識做簡要說明

簡單的多執行緒

import threading,time

def test1(x):
  time.sleep(5)
  print(x**x)

#下面定義兩個執行緒呼叫test1這個函式,建立多執行緒使用如下語法,target後面跟函式名,args傳遞實參,實參需要以元組形式傳遞
start_time = time.time()
t1 = threading.Thread(target=test1,args=(5,))
t2 = threading.Thread(target=test1,args=(6,))
#啟動多執行緒
t1.start()
t2.start()
end_time = time.time()
total_time = end_time - start_time
print("two Thread used %s time"%total_time) #由於使用多執行緒,t1 t2啟動以後並不會等待期執行完程式才繼續往後走,因為主程式就是主執行緒和t1 t2是並行執行的,主程式執行到此t1 t2並未執行完成

time.sleep(6)
#多執行緒啟動數量比較多時可以使用for迴圈,多執行緒並行執行,列印的結果有可能不是按照啟動順序來列印的
for i in range(5):
  t3 = threading.Thread(target=test1,args=(i,))
  t3.start()
time.sleep(6)

主執行緒等待非主執行緒執行完畢才繼續執行 join方法

#有些情況主執行緒需要子執行緒執行完畢後,有可能是將資料處理完畢後才執行接下來的主執行緒的東西
start_time1 = time.time()
tl = [] #將多執行緒的物件存起來,用於後面join方法
for i in range(5):
  t4 = threading.Thread(target=test1,))
  t4.start()
  tl.append(t4)
for t in tl: #將多執行緒併發join,參加join的子執行緒執行完畢後才繼續執行下面的主執行緒。
  t.join()
end_time1 = time.time()
total_time1 = end_time1 - start_time1
print(total_time1) #此次執行時間大約就是5s
#如果多個子執行緒一些join一些沒有join主執行緒怎麼處理???部分子執行緒join主執行緒會等join時間最長的子執行緒結束後才繼續,未參與join的子執行緒仍然和主執行緒並行執行
t5 = threading.Thread(target=test1,))
t6 = threading.Thread(target=test1,))
t5.start()
t6.start()
t5_join_start_time = time.time()
t5.join()
time.sleep(10)
t5_join_end_time = time.time()
print("t5 join time is %s"%(t5_join_end_time - t5_join_start_time)) #實際耗時15s

守護執行緒 setDeamon

#守護程序,即主執行緒結束以後所有的其它執行緒也立即結束,不用等其它執行緒執行完畢;正常情況即使沒加join主執行緒執行完畢當其它執行緒未執行完畢程式也不會退出,必須等待所有執行緒執行完畢程式才結束,類似主程式在末尾有預設的join
def test1(x):
  time.sleep(5)
  print("i an other Thread",x**x)

for i in range(5):
  t = threading.Thread(target=test1,))
  t.setDaemon(True)
  t.start()

print("Main Thread is done") #整個程式結束,不會等待守護執行緒列印操作執行完畢就直接結束了

遞迴鎖 Rlock

#遞迴鎖,一個鎖裡面巢狀著鎖,如果不使用遞迴鎖會導致釋放鎖邏輯錯誤,整個程式就跑偏了;使用遞迴鎖後程序會維護一個加鎖 解鎖的資料結構,保證釋放鎖不會出問題
lock = threading.Lock()
def test2():
  lock.acquire()
  print("this is test2")
  lock.release()

def test3():
  lock.acquire()
  print("this is test3")
  lock.release()

def test4():
  lock.acquire()
  test2()
  print("this is test4")
  test3()
  lock.release()

rlock_test = threading.Thread(target=test4)
rlock_test.start()

while threading.active_count() != 1:
  print("current thread count is",threading.active_count()) #整個程式一直在列印有兩個執行緒,非主執行緒的鎖嵌套出問題導致無法退出,整個程式卡死
  time.sleep(1)

將lock = threading.Lock()修改為lock = threading.RLock()整個程式就能正常結束;正常結束的輸出如下

this is test2
this is test4
current thread count is 2
this is test3

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。