執行緒的建立和各種鎖
執行緒的兩種建立方式:(重點)
一方式
From threading import Thread
Def f1(n):
Print(n)
main:
T = Thread(target=f1,args=(1,))
T.start()
二方式
Class MyThread(Thread):
Def __init__(self,n):
Super().__init__()
Self.n = n
Def run(self):
Pass
Main:
T = MyThread(5)
T.start()
程序:資源分配單位
執行緒:cpu執行單位(實體)
多執行緒和多程序執行時間對比:
import time from threading import Thread from multiprocessing import Process def f1(): a = 100 b = a**2 if __name__ == '__main__': t_time = time.time() t_lis = [] for i in range(10): t = Thread(target=f1,) t.start() t_lis.append(t) [i.join() for i in t_lis] t__time = time.time() t___time = t__time - t_time p_time = time.time() p_lis = [] for i in range(10): p = Process(target=f1, ) p.start() p_lis.append(p) [i.join() for i in p_lis] p__time = time.time() p___time = p__time - p_time print("多執行緒時間:", t___time) print("多程序時間:", p___time)
鎖:犧牲了效率,保證了資料安全(重點)
執行緒的建立和銷燬的開銷特別小
執行緒之間資源共享,共享的是同一個程序中的資源
資源共享就涉及到資料安全問題,加鎖來解決
from threading import Thread,Lock
loc = Lock()
t = thread(target=f1,args=(loc,))
鎖: ( 或者用with )
loc.acquire()
程式碼
loc.release()
import time from threading import Thread,Lock num = 10 def f1(n): global num with n : tmg = num tmg -= 1 time.sleep(0.001) num = tmg print(f"子執行緒執行完的num的值為:{num}") if __name__ == '__main__': loc = Lock() t_lis = [] for i in range(10): t = Thread(target=f1,args=(loc,)) t.start() t_lis.append(t) [i.join() for i in t_lis] print(f"num的值為:{num}")
死鎖現象:出現在鎖巢狀的時候,雙方互相搶對方已經拿到的鎖,導致雙方互相等待,天長地久永不分離,死鎖現象(重點)
def fun1(n,m): n.acquire() print(f">>>1號搶到了A鎖") time.sleep(0.5) m.acquire() print(f">>>1號搶到了B鎖") m.release() n.release() def fun2(n,m): m.acquire() print(f">>>2號搶到了B鎖") time.sleep(0.5) n.acquire() print(f">>>2號搶到了A鎖") n.release() m.release() if __name__ == '__main__': locA = Lock() locB = Lock() t1 = Thread(target=fun1,args=(locA,locB,)) t2 = Thread(target=fun2,args=(locA, locB,)) t1.start() t2.start()
遞迴鎖:解決死鎖現象(重點)
Rlock 首先本身就是個互斥鎖,維護了一個計數器,每次acquire就+1,release就-1,當計數器為0的時候,大家才能搶這個鎖
import time from threading import Thread,RLock def fun1(n,m): n.acquire() print(f">>>1號搶到了A鎖") time.sleep(0.5) m.acquire() print(f">>>1號搶到了B鎖") m.release() n.release() def fun2(n,m): m.acquire() print(f">>>2號搶到了B鎖") time.sleep(0.5) n.acquire() print(f">>>2號搶到了A鎖") n.release() m.release() if __name__ == '__main__': locA = locB = RLock() t1 = Thread(target=fun1,args=(locA,locB,)) t2 = Thread(target=fun2,args=(locA, locB,)) t1.start() t2.start()
守護執行緒(小重點)
守護執行緒:等待所有非守護執行緒的結束才結束
守護程序:主程序程式碼執行結束,守護程序就隨之結束
GIL鎖(重點) : cpython直譯器上的一把互斥鎖.瞭解python怎麼執行執行緒
執行緒的訊號量,事件 與 程序的訊號量,事件 邏輯一樣.(瞭解內容,見前面程序的部落格)