一個正在被運行的程序就稱之爲進程,是程序具體執行過程,一種抽象概念python
進程來自於操做系統 linux
程序就是一堆計算機能夠識別文件,程序在沒有被運行就是躺在硬盤上的一堆二進制程序員
運行程序時,要從硬盤讀取數據到內存中,CPU從內存讀取指令並執行 ,編程
一旦運行就產生了進程 瀏覽器
一個程序能夠屢次執行 產生多個進程,可是進程之間相互獨立安全
當咱們右鍵運行了一個py文件時 ,其實啓動的是python解釋器,你的py文件實際上是看成參數傳給瞭解釋器 網絡
阻塞 : 程序遇到io操做是就進入了阻塞狀態 數據結構
本地IO input print sleep read write 併發
網絡IO recv senddom
非阻塞: 程序正常運行中 沒有任何IO操做 就處於非阻塞狀態
阻塞 非阻塞 說的是程序的運行狀態
併發: 多個任務看起來同時在處理 ,本質上是切換執行 速度很是快
並行: 多個任務真正的同時執行 必須具有多核CPU 纔可能並行
併發 並行 說的是 任務的處理方式
提升效率
根本方法就是讓程序儘量處於運行狀態
減小IO 儘量多佔用CPU時間
緩衝區就是用於減小IO操做的
菜譜: 就是程序
作菜的過程:就是進程
1.直接實例化Process ,將要執行任務用target傳入
2.繼承Process類 ,覆蓋run方法 將任務放入run方法中
import os
from multiprocessing import Process
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name = name
# 繼承Procee覆蓋run方法將要執行任務發到run中
def run(self):
print(self.name)
print("子進程 %s running!" % os.getpid())
print("子進程 %s over!" % os.getpid())
if __name__ == '__main__':
# 建立時 不用再指定target參數了
p = MyProcess("rose")
p.start()
print("父進程over!")
Process的對象具有一個join函數
用於提升子進程優先級 ,使得父進程等待子進程結束
指的是,父進程先結束 ,而子進程還在運行着,
孤兒進程無害,有 其存在的必要性
例如:qq開啓了瀏覽器,qq先退出了 瀏覽器應該繼續運行
孤兒進程會被操做系統接管
值得是,子進程已經結束了,可是操做系統會保存一些進程信息,如PID,運行時間等,此時這個進程就稱之爲殭屍進程
殭屍進程若是太多將會佔用大量的資源,形成系統沒法開啓新新進程
linux 中有一個wai/waitpid 用於父進程回收子進程資源
python會自動回收殭屍進程
# p.join() # 等待子進程結束
# p.terminate() # 終止進程
# print(p.name) # 進程的名稱
# print(p.is_alive()) #是否存活
# p.terminate() # 與start同樣 都是給操做系統發送指令 因此會有延遲
# print(p.is_alive())
# print(p.pid)
# print(p.exitcode) # 獲取退出碼
什麼是守護進程
進程是一個正在運行的程序
守護進程也是一個普通進程
意思是一個進程能夠守護另外一個進程
康熙要是一個進程的話,後宮佳麗都是守護者
若是康熙掛了, 後宮佳麗們要陪葬
若是b是a的守護進程,a是被守護的進程,a要是掛了,b也就隨之結束了
from multiprocessing import Process import time # 妃子的一輩子
def task(): print("入宮了.....") time.sleep(50) print("妃子病逝了......") if __name__ == '__main__': # 康熙登基了
print("登基了.....") # 找了一個妃子
p = Process(target=task) # 設置爲守護進程 必須在開啓前就設置好
p.daemon = True p.start() # 康熙駕崩了
time.sleep(3) print("故事結束了!")
父進程交給了子進程一個任務,任務尚未完成父進程就結束了,子進程就沒有繼續執行的意義了
例如:qq 接收到一個視頻文件,因而開啓了一個子進程來下載,若是中途退出了qq,下載任務就沒必需要繼續運行了
互斥鎖 互相排斥的鎖,我在這站着你就別過來,(若是這個資源已經被鎖了,其餘進程就沒法使用了)
須要強調的是: 鎖 並非真的把資源鎖起來了,只是在代碼層面限制你的代碼不能執行
併發將帶來資源的競爭問題
當多個進程同時要操做同一個資源時,將會致使數據錯亂的問題
以下列所示:
加join,
弊端 1.把本來併發的任務變成了穿行,避免了數據錯亂問題,可是效率下降了,這樣就不必開子進程了
2.本來多個進程之間是公平競爭,join執行的順序就定死了,這是不合理的
就是給公共資源加鎖,互斥鎖
互斥鎖 互相排斥的鎖,我在這站着你就別過來,(若是這個資源已經被鎖了,其餘進程就沒法使用了)
鎖 並非真的把資源鎖起來了,只是在代碼層面限制你的代碼不能執行
1. join是固定了執行順序,會形成父進程等待子進程
鎖依然是公平競爭誰先搶到誰先執行,父進程能夠作其餘事情
2.最主要的區別:
join是把進程的任務所有串行
鎖能夠鎖任意代碼 一行也能夠 能夠本身調整粒度
from multiprocessing import Process,Lock import time,random def task1(lock): # 要開始使用了 上鎖
lock.acquire() #就等同於一個if判斷
print("hello iam jerry") time.sleep(random.randint(0, 2)) print("gender is boy") time.sleep(random.randint(0, 2)) print("age is 15") # 用完了就解鎖
lock.release() def task2(lock): lock.acquire() print("hello iam owen") time.sleep(random.randint(0,2)) print("gender is girl") time.sleep(random.randint(0,2)) print("age is 48") lock.release() def task3(lock): lock.acquire() print("hello iam jason") time.sleep(random.randint(0,2)) print("gender is women") time.sleep(random.randint(0,2)) print("age is 26") lock.release() if __name__ == '__main__': lock = Lock() p1 = Process(target=task1,args=(lock,)) p2 = Process(target=task2,args=(lock,)) p3 = Process(target=task3,args=(lock,)) p1.start() # p1.join()
p2.start() # p2.join()
p3.start() # p3.join()
# print("故事結束!")
# 鎖的僞代碼實現
# if my_lock == False: # my_lock = True # #被鎖住的代碼
my_lock = False 解鎖
注意1: 不要對同一把執行多出acquire 會鎖死致使程序沒法執行 一次acquire必須對應一次release
l = Lock() l.acquire() print("搶到了!") l.release() l.acquire() print("強哥毛線!")
注意2:想要保住數據安全,必須保住全部進程使用同一把鎖
進程間通信
通信指的就是交換數據
進程之間內存是相互隔離的,當一個進程想要把數據給另一個進程,就須要考慮IPC
只能單向通信,數據都是二進制
在硬盤上建立共享文件
缺點:速度慢
優勢:數據量幾乎沒有限制
編程複雜度較高
共享內存:必須由操做系統來分配 要掌握的方式*****
優勢: 速度快
缺點: 數據量不能太大
Manager提供不少數據結構 list dict等等
Manager所建立出來的數據結構,具有進程間共享的特色
from multiprocessing import Process,Manager,Lock import time def task(data,l): l.acquire() num = data["num"] # time.sleep(0.1) data["num"] = num - 1 l.release() if __name__ == '__main__': # 讓Manager開啓一個共享的字典
m = Manager() data = m.dict({"num":10}) l = Lock() for i in range(10): p = Process(target=task,args=(data,l)) p.start() time.sleep(2) print(data)
須要強調的是 Manager建立的一些數據結構是不帶鎖的 可能會出現問題
幫咱們處理了鎖的問題 重點
隊列是一種特殊的數據結構,先存儲的先取出 就像排隊 先進先出
相反的是堆棧,先存儲的後取出, 就像衣櫃 桶裝薯片 先進後出
擴展:
函數嵌套調用時 執行順序是先進後出 也稱之爲函數棧
調用 函數時 函數入棧 函數結束就出棧
from multiprocessing import Queue # 建立隊列 不指定maxsize 則沒有數量限制
q = Queue(3) # 存儲元素 # q.put("abc") # q.put("hhh") # q.put("kkk")
# print(q.get()) # q.put("ooo") # 若是容量已經滿了,在調用put時將進入阻塞狀態 直到有人從隊列中拿走數據有空位置 纔會繼續執行
#取出元素 # print(q.get())# 若是隊列已經空了,在調用get時將進入阻塞狀態 直到有人從存儲了新的數據到隊列中 纔會繼續
# print(q.get()) # print(q.get())
#block 表示是否阻塞 默認是阻塞的 # 當設置爲False 而且隊列爲空時 拋出異常
q.get(block=True,timeout=2) # block 表示是否阻塞 默認是阻塞的 # 當設置爲False 而且隊列滿了時 拋出異常 # q.put("123",block=False,) # timeout 表示阻塞的超時時間 ,超過期間仍是沒有值或仍是沒位置則拋出異常 僅在block爲True有效
## 是什麼
模型 就是解決某個問題套路
產生數據的一方稱之爲生產者
處理數據的一方稱之爲消費者
例如: 爬蟲 生活中處處都是這種模型
飯店 廚師就是生產者 你吃飯的人就是消費者
## 生產者和消費者出啥問題了? 解決什麼問題
生產者和消費,處理速度不平衡,一方快一方慢,致使一方須要等待另外一方
## 生產者消費者模型解決這個問題的思路: 怎麼解決
本來,雙方是耦合 在一塊兒,消費必須等待生產者生成完畢在開始處理, 反過來
若是消費消費速度太慢,生產者必須等待其處理完畢才能開始生成下一個數據
### 解決的方案:
將雙方分開來.一專門負責生成,一方專門負責處理
這樣一來數據就不能直接交互了 雙方須要一個共同的容器
生產者完成後放入容器,消費者從容器中取出數據
這樣就解決了雙發能力不平衡的問題,作的快的一方能夠繼續作,不須要等待另外一方
案例:
def eat(q): for i in range(10): # 要消費
rose = q.get() time.sleep(random.randint(0, 2)) print(rose,"吃完了!") # 生產任務
def make_rose(q): for i in range(10): # 再生產
time.sleep(random.randint(0, 2)) print("第%s盤青椒肉絲製做完成!" % i) rose = "第%s盤青椒肉絲" % i # 將生成完成的數據放入隊列中
q.put(rose) if __name__ == '__main__': # 建立一個共享隊列
q = Queue() make_p = Process(target=make_rose,args=(q,)) eat_p = Process(target=eat,args=(q,)) make_p.start() eat_p.start()