線程是一種多任務編程的方式,可使用計算機多核資源。線程又被稱爲輕量級的進程java
線程特徵python
* 線程是計算機核心分配的最小單位
* 一個進程能夠包含多個線程
* 線程也是一個運行過程,也要消耗計算機資源。多個線程共享其進程的資源和空間
* 線程也擁有本身特有的資源屬性,好比指令集,TID等
* 線程不管建立仍是刪除仍是運行資源消耗都小於進程
* 多個線程之間並行執行,互不干擾編程
from threading import Threadc#
t = Thread(target, [, args], [kwargs])安全
建立線程對象多線程
t.start() 啓動線程併發
t.join([timeout]) 回收線程app
import threading import os a = 1 # 線程函數 def music(): print("進程pid號", os.getpid()) global a print("a = ",a) a = 10000 t = threading.Thread(target=music) # 建立線程對象 t.start() # 啓動線程 print("進程pid號", os.getpid()) t.join() # 回收線程 print("Main a:",a) # 進程pid號 12549 # 進程pid號 12549 # a = 1 # Main a: 10000
os.getpid獲取的是進程的pid號,線程是進程中的一個成員.ide
線程中改的變量,是進程中的變量.並無新開闢一個空間.函數
t.is_alive() 查看線程狀態
t.name 線程名稱 默認Thread-1
t.setName() 設置線程名稱
threading.currentThread() 獲取當前線程對象
1 from threading import Thread,currentThread 2 from time import sleep 3 4 #線程函數 5 def fun(sec): 6 print("線程屬性測試") 7 sleep(sec) 8 #獲取線程對象 getName()獲取名字 9 print("%s 線程結束"%currentThread().getName()) 10 11 thread = [] 12 13 for i in range(3): 14 t = Thread(target = fun,name = "tedu%d"%i,\ 15 args = (3,)) 16 thread.append(t) 17 t.start() 18 print(t.is_alive()) #查看進程狀態 19 20 thread[1].setName('Tarena') #設置線程名稱 21 print(thread[2].name) #獲取線程名稱 22 23 #回收線程 24 for i in thread: 25 i.join() 26 27 # 線程屬性測試 28 # True 29 # 線程屬性測試 30 # True 31 # 線程屬性測試 32 # True 33 # tedu2 34 # Tarena 線程結束 35 # tedu0 線程結束 36 # tedu2 線程結束
t.daemon
默認狀況下,主線程的結束不會影響分支線程,若是設置爲True則主線程退出分支線程也會退出
設置方法:
t.daemon = True
t.setDaemon()
線程daemon屬性的設置在start前;通常設置daemon後不會使用join
from threading import Thread from time import sleep def fun(): sleep(3) print("線程屬性測試") t = Thread(target=fun, name = "Tarena") # 主線程退出分支線程也退出 t.setDaemon(True) t.start() t.setName("Tedu") print("Name:",t.getName()) # 線程名稱 print("Alive:",t.is_alive()) # 線程生命週期 print("is Daemon",t.isDaemon()) # 主進程隨着分支進程退出
使用方法
from threading import Thread class ThreadClass(Thread): # 重寫父類init def __init__(self, *args, **kwargs): self.attr = args[0] super().__init__() # 加載父類init def fun1(self): print("函數1") def fun2(self): print("函數2") # 重寫run,邏輯調用 def run(self): self.fun1() self.fun2() t = ThreadClass("abc") t.start() t.join() # 函數1 # 函數2
1.通訊方法:線程間使用全局變量進行通訊
2. 共享資源爭奪
3. 同步互斥機制
同步 : 同步是一種協做關係,爲完成操做,多進程或者線程間造成一種協調,按照必要的步驟有序執行操做。
互斥 : 互斥是一種制約關係,當一個進程或者線程佔有資源時會進行加鎖處理,此時其餘進程線程就沒法操做該資源,直到解鎖後才能操做。
from threading import Event
e = Event() 建立線程event對象
e.wait([timeout]) 阻塞等待e被set
e.set() 設置e,使wait結束阻塞
e.clear() 使e回到未被設置狀態
e.is_set() 查看當前e是否被設置
from threading import Thread,Event s = None # 用於通訊 e = Event() # 建立event對象 def 楊子榮(): print("楊子榮前來拜山頭") global s s = "天王蓋地虎" e.set() # 對e設置 t = Thread(target=楊子榮) t.start() print("說對口令就是本身人") e.wait() # 阻塞等待口令說出 if s == '天王蓋地虎': print("寶塔鎮河妖") print("確認過眼神,你是對的人") else: print("打死他...") t.join()
from threading import Lock
lock = Lock() 建立鎖對象
lock.acquire() 上鎖 若是lock已經上鎖再調用會阻塞
lock.release() 解鎖
with lock: # 上鎖
...
...
with代碼塊結束自動解鎖
from threading import Thread,Lock a = b = 0 lock = Lock() # 定義鎖 def value(): while True: lock.acquire() # 上鎖 if a != b: print("a = %d,b = %d"%(a,b)) lock.release() # 解鎖 t = Thread(target = value) t.start() while True: # 上鎖 with lock: a += 1 b += 1 # 自動解鎖 t.join()
GIL (全局解釋器鎖)
python ---》 支持線程操做 ---》IO的同步和互斥 --》 加鎖 ----》 超級鎖,給解釋器加鎖
後果:一個解釋器,同一時刻只解釋一個線程,此時其餘線程須要等待。大大下降了python線程的執行效率
python GIL問題解決方案
* 修改c解釋器
* 儘可能使用多進程進行並行操做
* python線程能夠用在高延遲多阻塞的IO情形
* 不使用cpython c# java作解釋器
分別測試 多進程 多線程 單進程執行相同的IO操做和CPU
#計算密集 def count(x,y): c = 0 while c < 7000000: x += 1 y += 1 c += 1 #io密集 def write(): f = open("test.txt",'w') for x in range(2000000): f.write("hello world\n") f.close() def read(): f = open("test.txt") lines = f.readlines() f.close()
操做的時間
#單進程程序 from test import * import time # t = time.time() # for i in range(10): # count(1,1) # print("Line cpu:",time.time() - t) t = time.time() for i in range(10): write() read() print("Line IO:",time.time() - t)
Line cpu: 8.15166711807251
Line IO: 6.841825246810913
from test import * import threading import time counts = [] t = time.time() for x in range(10): th = threading.Thread(target = count,args = (1,1)) th.start() counts.append(th) for i in counts: i.join() print("Thread cpu",time.time() - t)
from test import * import threading import time counts = [] def io(): write() read() t = time.time() for x in range(10): th = threading.Thread(target = io) th.start() counts.append(th) for i in counts: i.join() print("Thread IO",time.time() - t)
Thread cpu 8.414522647857666
Thread IO 6.023292541503906
from test import * import multiprocessing import time counts = [] t = time.time() for x in range(10): th = multiprocessing.Process\ (target = count,args = (1,1)) th.start() counts.append(th) for i in counts: i.join() print("Process cpu",time.time() - t)
from test import * import multiprocessing import time counts = [] def io(): write() read() t = time.time() for x in range(10): th = multiprocessing.Process(target = io) th.start() counts.append(th) for i in counts: i.join() print("Process IO",time.time() - t)
Process cpu 4.079084157943726
Process IO 3.2132551670074463
使用狀況: