day41 Pyhton 併發程式設計04
內容回顧
socket
最底層的網路通訊
所有的網路通訊都是基於socket
程序
什麼是程序?
是作業系統的發展過程中,為了提高cpu的利用率,在作業系統同時執行多個程式的時候,為了資料的安全\程式碼不混亂而創造的一個概念
每一個程式執行起來都至少是一個程序
程序是計算機中最小的資源分配單位
程序被作業系統排程的,有很多相關的演算法--早期的作業系統
程序之間是資料隔離的
程序的三狀態 就緒 執行 阻塞
同步非同步
同步:一個任務的執行依賴另一個事務的結束
join lock
非同步:一個任務的執行不依賴另一個事務的結束
start terminate
阻塞非租塞
阻塞 :accept recv recvfrom queue.get join
非租塞: setblocking = False
併發並行
並行是特殊的併發
並行就是 同一時刻 兩個以上的程式同時在cou上執行
併發就是 同一時段 兩個以上的程式看起來在同時執行
IO概念: 檔案操作 資料庫操作 網路傳輸 使用者輸入輸出
Input 得到bytes/str
Output 傳送資料/輸出資料
因為程序與程序之間本質上是非同步切資料隔離
守護程序:子程序等待主程序的程式碼結束就結束了
同步控制
join
鎖 -互斥鎖: 多個程序同時對一個數據進行操作的時候,操作同一個檔案/資料庫/管道/Manager.dict
訊號量
事件
資料共享 - 資料不安全
Manager
IPC-程序之間通訊
管道
佇列 - 生產者消費者模型(為了解決資料的生產和處理的效率問題)
第三方工具(訊息佇列,訊息中介軟體)
程序池
解決大量任務 開啟多個程序的開銷過大的問題
節省資源,提高併發效率的
一般開程序數 cpu_count *1 or 2
今日內容
初識程序
為什麼要有執行緒
執行緒在作業系統中有什麼特點
執行緒在python語言中有什麼特點
GIL全域性直譯器鎖
為什麼要有全域性直譯器鎖
在python中如何開啟執行緒
執行緒的基礎的使用
執行緒的概念
# 多程序 socket server # 只要來了一個client請求 開一個程序 # 程序開多了就會卡 # 程序的排程 # 程序的開啟的開銷 # 給作業系統的負擔 # 資料\檔案\程式碼 # 記錄當前的執行位置 # 假設有一個機制 # 開啟程序的開銷變短 # 排程的時間也變短 # 作業系統減負 # 執行緒是計算機中被CPU排程的最小單位 # 執行緒 : 輕量級的程序/輕型程序 # 執行緒本身創建出來就是為了解決併發問題的 # 並且它的整體效率比程序要高 # 但是執行緒實際上也有一些效能上的限制\管理排程開銷 # 在整個程式界: # 如果你的程式需要資料隔離 : 多程序 # 如果你的程式對併發的要求非常高 : 多執行緒 # socketserver 多執行緒的 # web的框架 django flask tornado 多執行緒來接收使用者併發的請求 # 執行緒 # 輕量級 # 在程序中資料共享 # 是程序的一部分,不能獨立存在的 # 計算機中能被CPU排程的最小單位 # 程序 # 對作業系統的壓力大 # 資料隔離 # 可以在作業系統中獨立存在 # 計算機中資源分配的最小單位 # 在整個程式設計界 # 同一個程序中的多個執行緒能不能同時使用多個cpu # python # 單核的 一個cpu # 多核的 作為一門指令碼語言 # 執行緒鎖這件事兒是有Cpython直譯器完成 # 對於python來說 同一時刻只能有一個執行緒被cpu訪問 # 徹底的解決了多核環境下的安全問題 # 執行緒鎖 : 全域性直譯器鎖 GIL # 1.這個鎖是鎖執行緒的 # 2.這個鎖是直譯器提供的 # 多執行緒仍然有它的優勢 # 你的程式中用到cpu真的多麼 # 如果100% 90%的時間都消耗在計算上,那麼cpython直譯器下的多執行緒對你來說確實沒用 # 但是你寫的大部分程式 的時間實際上都消耗在了IO操作上 # 遇到高計算型 # 開程序 4個程序 每個程序裡開n個執行緒 # 換個直譯器
threading模組
import os
import time
from threading import Thread # Process 程序類 # Thread 執行緒類 # 1.初識執行緒模組 def func(): print('start',os.getpid()) time.sleep(1) print('end') if __name__ == '__main__': t = Thread(target=func) t.start() for i in range(5): print('主執行緒',os.getpid()) time.sleep(0.3)
import time from threading import Thread def func(): n = 1 + 2 + 3 n ** 2 if __name__ == '__main__': start = time.time() lst = [] for i in range(100): t = Thread(target=func) t.start() lst.append(t) for t in lst: t.join() print(time.time() - start)#0.026000261306762695 # import time # from multiprocessing import Process as Thread # def func(): # n = 1 + 2 + 3 # n**2 # # if __name__ == '__main__': # start = time.time() # lst = [] # for i in range(100): # t = Thread(target=func) # t.start() # lst.append(t) # for t in lst: # t.join() # print(time.time() - start)#15.187999963760376
# 3.執行緒的資料共享 from threading import Thread n = 100 def func(): global n n -= 1 t = Thread(target=func) t.start() t.join() print(n)
# 4.開啟執行緒的另一種方式 from threading import Thread class Mythread(Thread): def __init__(self,arg): super().__init__() self.arg = arg def run(self): print('in son',self.arg) t = Mythread(123) t.start()
# 5.threading模組中的其他功能 import time from threading import Thread,currentThread,activeCount,enumerate class Mythread(Thread): def __init__(self,arg): super().__init__() self.arg = arg def run(self): time.sleep(1) print('in son',self.arg,currentThread()) for i in range(10): t = Mythread(123) t.start() print(t.ident) print(activeCount()) print(enumerate())
守護執行緒
import time from threading import Thread def func(): while True: print('in func') time.sleep(0.5) def func2(): print('start func2') time.sleep(10) print('end func2') Thread(target=func2).start() t = Thread(target=func) t.setDaemon(True) t.start() print('主執行緒') time.sleep(2) print('主執行緒結束')
守護程序 只守護主程序的程式碼,主程序程式碼結束了就結束守護,守護程序在主程序之前結束
守護執行緒 隨著主執行緒的結束才結束,守護執行緒是怎麼結束的
程序 terminate 強制結束一個程序的
執行緒 沒有強制結束的方法
執行緒結束 : 執行緒內部的程式碼執行完畢 那麼就自動結束了