並發編程之 進程


一、前提介紹

1.1 操作系統發展史

點擊這里查看詳細信息:操作系統發展史

1.2 多道技術
空間上的復用:多個程序共用一套設備,是多道技術實現時間上的復用的基礎 時間上的復用:單個CPU的電腦上,起多個應用程序,CPU通過快速切換,給人的感覺是同時運行的 CPU切換的情況: 1.一個任務占用時間過長或被操作系統強行剝奪走CPU的執行權限(比起串行效率反而降低) 2.一個任務執行過程中遇到io操作,也會被操作系統強行剝奪走CPU的執行權限(比起串行效率提高) 並發:看上去像是同時進行的,但是實際上是CPU快速切換實現的 並行:同時運行

二、進程

2.1 進程介紹
程序:一堆代碼
進程:正在運行的程序
進程是一個實體,每一個進程都有它自己獨立的內存空間
2.2 進程調度
1.先來先服務(FCFS):對短作業不利
2.短作業優先服務(SJ/PF):對長作業不利
3.時間片輪轉
4.多級反饋隊列
2.3 進程狀態轉換

2.4 同步與異步,阻塞與非阻塞
同步和異步:針對任務的提交方式
    同步:提交任務之后原地等待任務的返回結果,期間不做任何事!
    異步:提交任務之后,不等待任務的返回結果,直接向下運行代碼!

阻塞和非阻塞:針對程序運行的狀態
    阻塞:遇到io操作 --> 阻塞態 非阻塞:就緒或者運行態 --> 就緒態、運行態
2.5 創建進程的兩種方式
# -----------調用函數----------------------- from multiprocessing import Process import time def task(name): # 這個是要創建的進程 print('%s is running' % name) time.sleep(3) print('%s is over' % name) # 注意:在windows系統中,創建進程會將代碼以模塊的方式從頭到尾加載一遍 # 一定要寫在if __name__ == '__main__': 代碼塊里面 # 強調:函數名一旦加括號,執行優先級最高,立刻執行 if __name__ == '__main__': p1 = Process(target=task, args=('zhangsan', )) # 實例化了一個Process對象 p1.start() print("this is main processing!") # -------------實例化對象------------------------- from multiprocessing import Process import time class MyProcess(Process): def __init__(self, name): super().__init__() self.name = name # 必須寫run方法(規定好的) def run(self): print('%s is running' % self.name) time.sleep(2) print('%s is end' % self.name) if __name__ == '__main__': obj = MyProcess('egon') obj.start() print("this is main processing")
2.6 join方法
from multiprocessing import Process import time def task(name,n): print('%s is running' % name) time.sleep(2) print('%s is over' % name) if __name__ == '__main__': start_time = time.time() p_list = [] for i in range(3): p = Process(target=task, args=('子進程%s' % i, i)) p.start() p_list.append(p) for i in p_list: i.join() print('this is main processing ', time.time()-start_time) # join的作用僅僅只是讓主進程等待子進程的結束,不會影響子進程的運行 # 下方為程序的運行結果,(結果不是固定的,但是每三行的順序是固定的,肯定是先running再over) """ 打印結果: 子進程2 is running 子進程0 is running 子進程1 is running 子進程2 is over 子進程0 is over 子進程1 is over this is main processing 3.1227028369903564 """
2.7 進程間的數據隔離與通信
# --------------進程間的數據隔離--------------------------- # 要驗證進程間的內存隔離,只需要在父進程中調用子進程 # 看子進程是否改變父進程的變量就行了 from multiprocessing import Process x = 100 def task(): global x x = 1 if __name__ == '__main__': p = Process(target=task) p.start() p.join() print('this is main processing', x) # 打印結果:this is main processing 100 # --------進程間的通信------------------------------------- from multiprocessing import Queue, Process # 基於隊列實現進程間的通信 def producer(q): q.put('this is producer!') def consumer(q): print(q.get()) if __name__ == '__main__': q = Queue() # 實例化隊列對象 p1 = Process(target=producer, args=(q,)) c1 = Process(target=consumer, args=(q,)) p1.start() c1.start() 
2.8 進程對象的其他相關方法
from multiprocessing import Process, current_process import time import os def task(): print('%s is running' % os.getpid()) # 獲取這個進程的id time.sleep(3) print('%s is over' % os.getppid()) # 獲取父進程的進程id if __name__ == '__main__': p1 = Process(target=task) p1.start() # 運行子進程 p1.terminate() # 殺死子進程 print(p1.is_alive()) # 判斷進程是否存活 print('this is main processing') """ 程序運行結果: 為什么在殺死子進程之后,任然顯示子進程存活? 是因為,將殺死子進程的命令發送給操作系統之后,在操作系統還沒殺死進程之前, 已經執行了進程是否存活這個命令,此時,系統還沒殺死進程,那么肯定返回True, 在此處,只需要在殺死進程的下一行,讓程序睡(暫停)一會兒,哪怕0.1秒, 都是可以正常顯示False True this is main processing """
2.9 僵屍進程與孤兒繼承
僵屍進程:
    子進程結束之后,不會立即釋放pid等資源信息。
主進程釋放子進程資源的兩種情況:
    主進程正常死亡
    join方法 任何進程都會步入僵屍進程,當主進程不停的創建子進程的時候,會有害 孤兒進程:主進程意外死亡,在Linux中有一個init幫助回收孤兒進程資源
2.10 守護進程
from multiprocessing import Process import time def task(name): print('%s 活着' % name) time.sleep(3) print("%s 正常死亡" % name) if __name__ == '__main__': p = Process(target=task, args=('李四總管',)) p.daemon = True # 必須在p.start開啟進程命令之前聲明 p.start() print('somebody is going to die!') 
2.11 互斥鎖
from multiprocessing import Process, Lock import json import time import random def search(i): with open('info', 'r', encoding='utf-8') as f: data = json.load(f) print(('用戶查詢余票數:%s' % data.get('ticket'))) def buy(i): # 買票之前還得先查有沒有票 with open('info', 'r', encoding='utf-8') as f: data = json.load(f) time.sleep(random.randint(1, 3)) # 模擬網絡延遲 if data.get('ticket') > 0: data['ticket'] -= 1 # 買票 with open('info', 'w', encoding='utf-8') as f: json.dump(data, f) print('用戶%s搶票成功' % i) else: print('用戶%s查詢余票為0' % i) def run(i, mutex): search(i) mutex.acquire() # 搶鎖 一把鎖不能同時被多個人使用,沒有搶到的人,就一直等下去 buy(i) mutex.release() # 釋放鎖 if __name__ == '__main__': mutex = Lock() for i in range(10): p = Process(target=run, args=(i, mutex)) p.start()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM