行程與執行緒的區別:
1. 執行緒是程式執行的最小單位,而行程是作業系統分配資源的最小單位;
2. 一個行程由一個或多個執行緒組成,執行緒是一個行程中代碼的不同執行路線;
3. 行程之間相互獨立,但同一行程下的各個執行緒之間共享程式的記憶體空間(包括代碼段,資料集,堆等)及一些行程級的資源(如打開檔案和信號等),某行程內的執行緒在其他行程不可見;
4. 調度和切換:執行緒背景關系切換比行程背景關系切換要快得多,
多執行緒:
多執行緒作業實體1:實作類似并發執行的效果,實際上并非并發,是多個執行緒間進行背景關系的切換
1 import threading 2 import time 3 def run(n): 4 print("task ",n ) 5 time.sleep(2) 6 print("task done",n) 7 start_time = time.time() 8 t_objs = [] #存執行緒實體 9 for i in range(50): 10 t = threading.Thread(target=run,args=("t-%s" %i ,)) # 實體化一個執行緒,指定執行緒執行run函式,args傳引數 11 t.start() # 啟動實體化的執行緒 12 t_objs.append(t) #為了不阻塞后面執行緒的啟動,不在這里join,先放到一個串列里 13 for t in t_objs: #回圈執行緒實體串列 14 t.join() # .join:等待執行緒執行完畢 15 print("----------all threads has finished...") 16 print("cost:",time.time() - start_time)
程式中,啟動了50個執行緒,每個執行緒在執行run方法時,均sleep兩秒,在程式結束時,實際上總體時間僅僅用了2秒多,
守護執行緒:設定子執行緒為守護執行緒時,當主執行緒結束時,子執行緒即結束,不會等待子執行緒執行完畢
守護執行緒實體:
1 import threading,time # 匯入模塊 2 3 def run(n): # 定義執行緒執行的函式 4 print("is task:", n, threading.current_thread()) 5 time.sleep(2) 6 print("task done",n, threading.current_thread()) 7 8 start_time = time.time() # 標記開始時間 9 10 for i in range(20): # 啟動20個執行緒 11 t = threading.Thread(target=run, args=("t-%s" % i,)) 12 t.setDaemon(True) # .setDaemon設定執行緒為守護執行緒 13 t.start() # 啟動執行緒 14 15 time.sleep(1) # 主執行緒sleep,程式執行時間完全取決于此sleep時間,與子執行緒的sleep無關 16 print("------threading runing done",threading.current_thread(),threading.active_count()) 17 print("cost:",time.time()- start_time) # 計算程式結束時間
程式中,以守護執行緒的形式啟動20個子執行緒,在主執行緒結束時子執行緒同時結束,即使子執行緒尚未執行完畢,程式總花費時間為1s多,
執行緒鎖:
由于多執行緒是同時執行的,多執行緒在修改同一個資料時,會出現修改后的資料不正確的情況,可以使用執行緒鎖實作執行緒串行修改資料,
1 import threading,time # 匯入模塊 2 3 def run(): # 執行緒執行函式 4 lock.acquire() # 加鎖 5 global num # 將num設定為全域變數 6 num += 1 7 print(num) 8 time.sleep(1) 9 lock.release() # 解鎖 10 11 num = 0 12 t_obj = [] # 執行緒串列 13 lock = threading.Lock() # 實體化一個執行緒鎖 14 for i in range(50): 15 t = threading.Thread(target=run) # 實體化一個執行緒 16 t.start() # 啟動執行緒 17 t_obj.append(t) # 將執行緒加入執行緒串列 18 19 for j in t_obj: # 回圈執行緒串列 20 j.join() 21 22 print("----------all threads has finished...",threading.current_thread(),threading.active_count()) 23 print("num:",num)
遞回鎖:
Rlock 遞回鎖,它相當于一個字典,記錄了鎖的門與鎖的對應值,當開門的時候會根據對應來開鎖.
1 import threading # 匯入模塊 2 3 def run1(): 4 lock.acquire() # 加鎖 5 global num1 6 num1 += 1 7 lock.release() # 解鎖 8 return num1 9 10 def run2(): 11 lock.acquire() # 加鎖 12 global num2 13 num2 += 1 14 lock.release() # 解鎖 15 return num2 16 17 def run3(): 18 lock.acquire() # 加鎖 19 res = run1() # run1函式中也有鎖操作 20 print("run1:",res) 21 res2 = run2() # run2函式中也有鎖操作 22 print("run2:",res2) 23 lock.release() # 解鎖 24 25 lock = threading.RLock() # 實體化鎖 26 num1 = 0 27 num2 = 0 28 t_obj = [] # 執行緒串列 29 for i in range(10): 30 t = threading.Thread(target=run3) 31 t.start() 32 t_obj.append(t) 33 while threading.active_count() != 1: 34 # print(threading.active_count()) # 列印當前運行的執行緒數 35 pass 36 else: 37 print("num1:%s, num2:%s" % (num1, num2))
信號量
1 import threading,time 2 3 def run(n): 4 semaphore.acquire() # 加鎖 5 time.sleep(1) 6 print("in run:",n) 7 semaphore.release() # 解鎖 8 9 semaphore = threading.BoundedSemaphore(3) # 加鎖的情況下,允許3個執行緒同時執行,不必等執行緒解鎖后下個執行緒才作業,3執行緒并發 10 for i in range(20): 11 t = threading.Thread(target=run,args=(i,)) 12 t.start()
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/45144.html
標籤:Python
上一篇:Python多行程解決方案multiprocessing ProcessPoolExecutor
下一篇:Python全堆疊課程002
