1. 多線程的概念
多線程類似於同時執行多個不同程序,多線程運行有如下優點:
使用線程可以把占據長時間的程序中的任務放到后台去處理。
用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度
程序的運行速度可能加快
在一些等待的任務實現上如用戶輸入、文件讀寫和網絡收發數據等,線程就比較有用了。在這種情況下我們可以釋放一些珍貴的資源如內存占用等等。
線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
每個線程都有他自己的一組CPU寄存器,稱為線程的上下文,該上下文反映了線程上次運行該線程的CPU寄存器的狀態。
指令指針和堆棧指針寄存器是線程上下文中兩個最重要的寄存器,線程總是在進程得到上下文中運行的,這些地址都用於標志擁有線程的進程地址空間中的內存。
線程可以被搶占(中斷)。
在其他線程正在運行時,線程可以暫時擱置(也稱為睡眠) -- 這就是線程的退讓。
2. Threading 多進程的使用案例:join()函數的理解
通過以下實例可以get到join()函數的作用:如果thread是某個子線程,則調用thread.join()的作用是確保thread子線程執行完畢后才能執行下一個線程。下面第一個例子中沒有調用join()函數,故沒有這個限制,所有線程執行順序都不定。
第二個例子中在每個子線程啟動start()后馬上調用了join()函數,這就確保了對於每一個子線程,必須等它執行完畢后才能執行下一個程序,故子線程是按順序執行的,且主線程中的print()方法是在所有的子線程執行完畢后才執行。
第三個例子中,對於子線程啟動start()后沒有馬上調用join()函數,故子線程的執行順序是不確定的,但是主線程中的print()前調用了每個子線程的join()函數,故print()要在所有的子線程執行完畢后才能執行。
(1)沒有使用join()函數,線程執行順序不定,主線程可能在所有子線程執行完之前就執行了
import threading
import time
def test(p):
time.sleep(0.001)
print(p)
ts = []
for i in range(15):
# target指定線程要執行的代碼,args指定該代碼的參數
th = threading.Thread(target=test, args=[i])
ts.append(th)
for i in ts:
i.start()
print("it is end !")
0
1
it is end !
4
2
3
5
(2)修改部分代碼如下:每次啟動子線程后,調用一次join()函數,可以看出線程按順序執行,且主線程在所有子線程執行完之 后才執行。
for i in ts:
i.start()
# 此處的join函數子線程按順序執行,即i線程跑完后才能繼續跑下一個線程
i.join()
print("it is end !")
0
1
2
3
4
5
it is end !
(3)修改部分代碼如下:可以看出子線程執行順序不定,但是主線程是在所有子線程執行完畢之后才執行的。
for i in ts:
i.start()
# 此處的join函數使子線程全部跑完再繼續往下跑子線程
for i in ts:
i.join()
print("it is end !")
1
0
4
5
2
3
it is end !
3. 全局鎖
(1)全局鎖(GIL)是一個很重要的概念。
在任意一個指定的時間,有且只有一個線程在運行 -》 python是線程安全的
(2)io操作經常用到多線程,如在修改某個文檔時,其他線程是不能進來干擾的。
a. 加鎖:acquire , 釋放鎖:release, 有加鎖就一定要釋放鎖
(3).rlock 可重入鎖: 如果前面忘記了release釋放鎖,正常是無法再獲取鎖的,rlock可實現再獲取鎖。
(4)實例:mlock.acquire()和mlock.release()之間的代碼是不間斷執行的,不會被其他線程干擾。
import threading
mlock = threading.Lock()
lst = list(range(20))
def change():
global lst
# mlock.acquire() # 加鎖
lst = [i+1 for i in lst]
lst = [i*2 for i in lst]
# mlock.release() #釋放鎖
print(lst)
for i in range(6):
d = threading.Thread(target=change)
d.start()
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40]
[6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82]
[14, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 142, 150, 158, 166]
[30, 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254, 270, 286, 302, 318, 334]
[62, 94, 126, 158, 190, 222, 254, 286, 318, 350, 382, 414, 446, 478, 510, 542, 574, 606, 638, 670]
[126, 190, 254, 318, 382, 446, 510, 574, 638, 702, 766, 830, 894, 958, 1022, 1086, 1150, 1214, 1278,
---------------------
作者:zhuzuwei
來源:CSDN
原文:https://blog.csdn.net/zhuzuwei/article/details/80927554
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!