python之路--關於執行緒的一些方法
阿新 • • 發佈:2019-01-11
1. 執行緒的兩種建立方式
from threading import Thread # 第一種建立方式 def f1(n): print('%s號執行緒任務'%n) def f2(n): print('%s號執行緒任務'%n) if __name__ == '__main__': t1 = Thread(target=f1,args=(1,)) t2 = Thread(target=f2,args=(2,)) t1.start() t2.start() print('主執行緒') # 第二種建立方式 class MyThread(Thread): def __init__(self,name): # super(MyThread, self).__init__() 和下面super是一樣的 super().__init__() self.name = name def run(self): print('hello girl :' + self.name) if __name__ == '__main__': t = MyThread('alex') t.start() print('主執行緒結束')
2. 檢視執行緒的pid
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('主執行緒') # 由於這些執行緒都是在一個程序中的,所以pid一致
3. 驗證執行緒之間的資料共享
import time from threading import Thread num = 100 def f1(n): global num num = 3 time.sleep(1) print('子執行緒的num', num) # 子執行緒的num 3 if __name__ == '__main__': thread = Thread(target=f1,args=(1,)) thread.start() thread.join() # 等待thread執行完在執行下面的程式碼 print('主執行緒的num', num) # 主執行緒的num 3
4. 多程序與多執行緒的效率對比
import time from threading import Thread from multiprocessing import Process def f1(): # io密集型 # time.sleep(1) # 計算型: 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('多執行緒的IO密集型執行時間:',t_dif_time) # 1.0017869472503662 還需要減1秒的time.sleep # print('多程序的IO密集型執行時間:',p_dif_time) # 1.2237937450408936 也需要減1秒的time.sleep print('多執行緒的計算密集型執行時間:', t_dif_time) # 3.58754563331604 print('多程序的計算密集型執行時間:', p_dif_time) # 2.1555309295654297
# 從上述程式碼中的執行效率可以看出來,多執行緒在執行IO密集型的程式的時候速度非常快,但是執行計算密集型的程式的時候很慢,所以說python這門語言不適合做大資料.
5. 互斥鎖,同步鎖
import time from threading import Lock, Thread num = 100 def f1(loc): # 加鎖 with loc: global num tmp = num tmp -= 1 time.sleep(0.001) num = tmp # 上面的程式碼相當於 num -= 1 if __name__ == '__main__': t_loc = Lock() t_list = [] for i in range(10): t = Thread(target=f1,args=(t_loc,)) t.start() t_list.append(t) [tt.join() for tt in t_list] print('主線的num',num)
6. 死鎖現象
import time from threading import Thread,Lock,RLock def f1(locA,locB): locA.acquire() print('f1>>1號搶到了A鎖') time.sleep(1) locB.acquire() print('f1>>1號搶到了B鎖') locB.release() locA.release() def f2(locA,locB): locB.acquire() print('f2>>2號搶到了B鎖') time.sleep(1) locA.acquire() print('f2>>2號搶到了A鎖') locA.release() locB.release() if __name__ == '__main__': # locA = locB = Lock() # 不能這麼寫,這麼寫相當於這兩個是同一把鎖 locA = Lock() locB = Lock() t1 = Thread(target=f1,args=(locA,locB)) t2 = Thread(target=f2,args=(locA,locB)) t1.start() t2.start() # 上面的程式碼表示f1 先搶到了A鎖,同時f2 搶到了B鎖,一秒後f1想去想B鎖,同時f2想去搶A鎖, # 由於鎖需要先放開才能繼續搶,導致了死鎖現象
7.遞迴鎖
import time from threading import Thread, Lock, RLock def f1(locA, locB): locA.acquire() print('f1>>1號搶到了A鎖') time.sleep(1) locB.acquire() print('f1>>1號搶到了B鎖') locB.release() locA.release() def f2(locA, locB): locB.acquire() print('f2>>2號搶到了B鎖') locA.acquire() time.sleep(1) print('f2>>2號搶到了A鎖') locA.release() locB.release() if __name__ == '__main__': locA = locB = RLock() #遞迴鎖,維護一個計數器,acquire一次就加1,release就減1 , acquire等於0的時候才可以搶 t1 = Thread(target=f1, args=(locA, locB)) t2 = Thread(target=f2, args=(locA, locB)) t1.start() t2.start()
# 遞迴鎖解決了死鎖現象,會讓程式碼繼續執行.
8. 守護執行緒
守護執行緒會等到所有的非守護執行緒執行結束後才結束
import time from threading import Thread from multiprocessing import Process #守護程序:主程序程式碼執行執行結束,守護程序隨之結束 #守護執行緒:守護執行緒會等待所有非守護執行緒執行結束才結束 def f1(): time.sleep(2) print('1號執行緒') def f2(): time.sleep(3) print('2號執行緒') if __name__ == '__main__': t1 = Thread(target=f1,) t2 = Thread(target=f2,) # t1.daemon = True # 1號程序 和 2 號程序都會列印 t2.daemon = True # 不會列印2號程序 t1.start() t2.start() print('主執行緒結束') # 與程序對比 p1 = Process(target=f1, ) p2 = Process(target=f2, ) p1.daemon = True # 只會列印 2號程序 p2.daemon = True # 只會列印1號程序 p1.start() p2.start() print('主程序結束')
9. GIL鎖的解釋