Python多線程threading join和守護線程setDeamon原理詳解

同一進程下的多個線程共享內存數據,多個線程之間沒有主次關係,相互之間可以操作;cpu執行的都是線程,默認程序會開一個主線程;進程是程序以及和程序相關資源的集合;某些場景下我們可以使用多線程來達到提高程序執行效率的目的,下面就多線程的一些基礎知識做簡要說明
簡單的多線程

mport 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, args=(i,))
  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, args=(5,))
t6 = threading.Thread(target=test1, args=(6,))
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, args=(i,))
  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

寫到這裏,給大家推薦一個資源很全的python學習聚集地,點擊進入,這裏有資深程序員分享以前學習

心得,學習筆記,還有一線企業的工作經驗,且給大家精心整理一份python零基礎到項目實戰的資料,

每天給大家講解python最新的技術,前景,學習需要留言的小細節

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章