線程 線程指的就是代碼的執行過程 進程其實是一個資源單位,而進程內的線程才是CPU上的執行單位 在傳統操作系統中,每個進程有一個地址空間,而且預設就有一個控制線程 線程顧名思義,就是一條流水線工作的過程,一條流水線必須屬於一個車間,一個車間的工作過程是一個進程 車間負責把資源整合到一起,是一個資源單 ...
線程
線程指的就是代碼的執行過程
進程其實是一個資源單位,而進程內的線程才是CPU上的執行單位
在傳統操作系統中,每個進程有一個地址空間,而且預設就有一個控制線程
線程顧名思義,就是一條流水線工作的過程,一條流水線必須屬於一個車間,一個車間的工作過程是一個進程
車間負責把資源整合到一起,是一個資源單位,而一個車間內至少有一個流水線
流水線的工作需要電源,電源就相當於CPU,所以進程只是用來把資源集中到一起(進程只是一個資源單位,或者說資源集合),而線程才是cpu上的執行單位。
多線程(即多個控制線程)的概念是:在一個進程中存在多個控制線程,多個控制線程共用該進程的地址空間,相當於一個車間內有多條流水線,都共用一個車間的資源。
例如:
北京地鐵與上海地鐵是不同的進程,而北京地鐵里的13號線是一個線程,北京地鐵所有的線路共用北京地鐵所有的資源,比如所有的乘客可以被所有線路拉。
線程詳解
線程和進程的區別
1.同一進程下的多個線程共用該進程內的資源
2.創建線程的開銷遠遠小於進程
創建線程的開銷遠遠小於進程 假設我們的軟體是一個工廠,該工廠有多條流水線,流水線工作需要電源,電源只有一個即CPU(單核CPU) 一個車間就是一個進程,一個車間至少一條流水線(一個進程至少一個線程) 創建一個進程,就是創建一個車間(申請空間,在該空間內建至少一條流水線) 而建線程,就只是在一個車間內造一條流水線,無需申請空間,所以創建開銷小 進程之間是競爭關係: 車間直接是競爭/搶電源的關係,競爭:不同的進程直接是競爭關係,是不同的程式員寫的程式運行的,迅雷搶占其他進程的網速,360把其他進程當做病毒乾死 線程之間是協作關係: 一個車間的不同流水線式協同工作的關係:同一個進程的線程之間是合作關係,不會自己乾自己線程對比進程詳解
多線程舉例
開啟一個字處理軟體進程,該進程肯定需要辦不止一件事情,比如監聽鍵盤輸入,處理文字,定時自動將文字保存到硬碟,
這三個任務操作的都是同一塊數據,因而不能用多進程。只能在一個進程里併發地開啟三個線程,如果是單線程,那就只能是,
鍵盤輸入時,不能處理文字和自動保存,自動保存時又不能輸入和處理文字。
開啟線程的兩種方式
Thread實例對象的方法 # isAlive(): 返回線程是否活動的。 # getName(): 返回線程名。 # setName(): 設置線程名。 threading模塊提供的一些方法: # threading.currentThread(): 返回當前的線程變數。 # threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啟動後、結束前,不包括啟動前和終止後的線程。 # threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
1 #方式一 2 from threading import Thread 3 import time 4 def sayhi(name): 5 time.sleep(2) 6 print('%s say hello' %name) 7 8 if __name__ == '__main__': 9 t=Thread(target=sayhi,args=('egon',)) 10 t.start() 11 print('主線程')方式一
1 #方式二 2 from threading import Thread 3 import time 4 class Sayhi(Thread): 5 def __init__(self,name): 6 super().__init__() 7 self.name=name 8 def run(self): 9 time.sleep(2) 10 print('%s say hello' % self.name) 11 12 13 if __name__ == '__main__': 14 t = Sayhi('egon') 15 t.start() 16 print('主線程')方式二
統一進程下線程間資源共用
統一進程下的多個線程共用該進程內的資源
代碼舉例:
1 from threading import Thread 2 3 n = 100 4 5 6 def task(): 7 global n 8 n = 0 9 10 11 if __name__ == '__main__': 12 t = Thread(target=task) 13 t.start() 14 t.join() 15 print(n)
守護線程
無論是進程還是線程,都遵循:守護xxx會等待xxx運行完畢後被銷毀
需要強調的是:運行完畢並非終止運行
#1.對主進程來說,運行完畢指的是主進程代碼運行完畢 #2.對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程才算運行完畢
詳細解釋:
#1 主進程在其代碼結束後就已經算運行完畢了(守護進程在此時就被回收),然後主進程會一直等非守護的子進程都運行完畢後回收子進程的資源(否則會產生僵屍進程),才會結束, #2 主線程在其他非守護線程運行完畢後才算運行完畢(守護線程在此時就被回收)。因為主線程的結束意味著進程的結束,進程整體的資源都將被回收,而進程必須保證非守護線程都運行完畢後才能結束。
1 from threading import Thread 2 import time 3 def sayhi(name): 4 time.sleep(2) 5 print('%s say hello' %name) 6 7 if __name__ == '__main__': 8 t=Thread(target=sayhi,args=('egon',)) 9 t.setDaemon(True) #必須在t.start()之前設置 10 t.start() 11 12 print('主線程') 13 print(t.is_alive()) 14 ''' 15 主線程 16 True 17 '''
1 from threading import Thread 2 import time 3 def foo(): 4 print(123) 5 time.sleep(1) 6 print("end123") 7 8 def bar(): 9 print(456) 10 time.sleep(3) 11 print("end456") 12 13 14 t1=Thread(target=foo) 15 t2=Thread(target=bar) 16 17 t1.daemon=True 18 t1.start() 19 t2.start() 20 print("main-------")迷惑人的例子
互斥鎖
1 from threading import Thread,Lock 2 import time 3 4 mutex=Lock() # 線程是共用資源的,所以不需要把鎖當參數傳 5 n=100 6 def task(): 7 global n 8 mutex.acquire() 9 temp=n 10 time.sleep(0.1) 11 n=temp-1 12 mutex.release() 13 14 if __name__ == '__main__': 15 t_l=[] 16 for i in range(100): 17 t=Thread(target=task) 18 t_l.append(t) 19 t.start() 20 21 for t in t_l: 22 t.join() 23 print(n)