1.線程: 一個進程可以有多個線程,共用一個進程的資源; 2.進程線程的區別: 進程是資源分配的最小單位,線程是程式執行的最小單位 3.python中線程模塊threading, 提供的類: Thread, Lock, Rlock, Semaphore, Event, 等等 4.線程的創建方式 6. ...
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鎖,互不影響。