python之執行緒相關操作
阿新 • • 發佈:2019-01-12
1.執行緒: 一個程序可以有多個執行緒,共享一個程序的資源;
2.程序執行緒的區別:
程序是資源分配的最小單位,執行緒是程式執行的最小單位
3.python中執行緒模組threading, 提供的類: Thread, Lock, Rlock, Semaphore, Event, 等等
4.執行緒的建立方式
# 第一種 # from threading import Thread # def f1(s): # print('我是%s' % s) # def f2(s): # print('我是%s' % s) # # if __name__ == '__main__':# t = Thread(target=f1, args=(1,)) # t1 = Thread(target=f1, args=(2,)) # t.start() # t1.start() # print('我是主執行緒') # 第二種 from threading import Thread class MyThread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self):print('%s今天還是不能皮' % self.name) if __name__ == '__main__': t = MyThread('Jerry') t.start() print('主執行緒')
6.檢視執行緒的程序id(同進程檢視方式一樣)
import os from threading import Thread def f1(n): print('1號', os.getpid()) print('%s號執行緒任務' % n) def f2(n): print('2號', os.getpid()) print('%s號執行緒任務' % n) if __name__ == '__main__': t1 = Thread(target=f1, args=(1,)) t2 = Thread(target=f2, args=(2,)) t1.start() t2.start() print('主執行緒', os.getpid()) print('主執行緒')
7. 在程序之間資料是空間隔離的, 而線上程中是資料共享的
import time from threading import Thread # 通過對全域性變數的修改來驗證執行緒之間是資料共享的, 共享同一程序中的資料 num = 100 def f1(): time.sleep(3) global num num = 3 print('子執行緒的num', num) if __name__ == '__main__': t = Thread(target=f1) t.start() t.join() # 等待子執行緒執行結束才繼續向下執行 print('主執行緒的num', num)
8.多程序和多執行緒的效率對比
對於io密集型的, 多執行緒的時間較快
def f1(): time.sleep(1) #io密集型 if __name__ == '__main__': # 檢視一下20個執行緒執行20個任務的執行時間 t_s_time = time.time() t_list = [] for i in range(5): t = Thread(target=f1,) t.start() t_list.append(t) [tt.join() for tt in t_list] t_e_time = time.time() t_dif_time = t_e_time - t_s_time # 檢視一下20個程序執行同樣的任務的執行時間 p_s_time = time.time() p_list = [] for i in range(5): p = Process(target=f1,) p.start() p_list.append(p) [pp.join() for pp in p_list] p_e_time = time.time() p_dif_time = p_e_time - p_s_time print('多執行緒的執行時間:', t_dif_time) print('多jincheng的執行時間:', p_dif_time)
計算型:
import time from threading import Thread from multiprocessing import Process def f1(): # 計算型: n = 10 for i in range(10000000): n = n + i if __name__ == '__main__': # 檢視一下20個執行緒執行20個任務的執行時間 t_s_time = time.time() t_list = [] for i in range(5): t = Thread(target=f1,) t.start() t_list.append(t) [tt.join() for tt in t_list] t_e_time = time.time() t_dif_time = t_e_time - t_s_time # 檢視一下20個程序執行同樣的任務的執行時間 p_s_time = time.time() p_list = [] for i in range(5): p = Process(target=f1,) p.start() p_list.append(p) [pp.join() for pp in p_list] p_e_time = time.time() p_dif_time = p_e_time - p_s_time print('多執行緒的執行時間:', t_dif_time) print('多jincheng的執行時間:', p_dif_time)
9.鎖,同步,互斥鎖 為了保護多線成中資料的完整性和執行緒間狀態的同步.(同進程的鎖一樣)
線上程鎖中, 會產生死鎖現象. 同時搶鎖
import time from threading import Thread, Lock, RLock def f1(locA, locB): # print('xxxx') # time.sleep(0.1) locA.acquire() print('f1>>1號搶到了A鎖') time.sleep(1) locB.acquire() print('f1>>1號搶到了B鎖') locB.release() locA.release() def f2(locA, locB): print('22222') time.sleep(0.1) locB.acquire() print('f2>>2號搶到了B鎖') locA.acquire() time.sleep(1) print('f2>>2號搶到了A鎖') locA.release() locB.release() if __name__ == '__main__': locA = Lock() locB = Lock() t1 = Thread(target=f1, args=(locA, locB)) t2 = Thread(target=f2, args=(locA, locB)) t1.start() t2.start()
遞迴鎖解決了 死鎖現象
import time from threading import Thread, Lock, RLock def f1(locA, locB): print('xxxxx') time.sleep(0.1) locA.acquire() print('f1>>>1號搶到了A鎖') time.sleep(1) locB.acquire() print('f1>>>2號搶到了B鎖') locB.release() locA.release() def f2(locA, locB): print('22222') time.sleep(0.1) locB.acquire() print('f2>>>1號搶到了A鎖') time.sleep(1) locA.acquire() print('f2>>>2號搶到了B鎖') locA.release() locB.release() if __name__ == '__main__': locA = locB = RLock() t1 = Thread(target=f1, args=(locA, locB)) t2 = Thread(target=f2, args=(locB, locA)) t1.start() t2.start()
10.多執行緒的程式不結束 和 多程序的程式不結束的區別
守護程序:主程序程式碼執行執行結束,守護程序隨之結束
守護執行緒:守護執行緒會等待所有非守護執行緒執行結束才結束
import time from threading import Thread from multiprocessing import Process # 守護程序:主程序程式碼執行執行結束,守護程序隨之結束 # 守護執行緒:守護執行緒會等待所有非守護執行緒執行結束才結束 def f1(): time.sleep(2) print('一號執行緒') def f2(): time.sleep(3) print('二號執行緒') def f3(): time.sleep(2) print('一號程序') def f4(): time.sleep(3) print('二號程序') if __name__ == '__main__': # t1 = Thread(target=f1,) # t2 = Thread(target=f2,) # # t1.daemon = True # 等非守護執行緒結束,守護執行緒才會結束 結果: 主執行緒結束 一號執行緒 二號執行緒 # t2.daemon = True # 結果: 主執行緒結束 一號執行緒 # t1.start() # t2.start() # print('主執行緒結束') p1 = Process(target=f3,) p2 = Process(target=f4,) # p1.daemon = True # 結果: 主程序 二號執行緒 p2.daemon= True # 結果: 主程序 一號執行緒 p1.start() p2.start() print('主程序')
11. GIL鎖 : cpython直譯器上的一把互斥鎖, Python直譯器由於設計時有GIL全域性鎖,導致了多執行緒無法利用多核
Python雖然不能利用多執行緒實現多核任務,但可以通過多程序實現多核任務。多個Python程序有各自獨立的GIL鎖,互不影響。