day34 并行并发、进程开启、僵尸及孤儿进程
1、并行與并發
什么是并行?
并行指的是多個進程同時被執行,是真正意義上的同時
什么是并發?
并發指的是多個程序看上去被同時執行,這是因為cpu在多個程序之間不停的進行切換,且切換的速度十分快,讓我們覺得自己在共享這段時間,所以不是真正意義上的同時
2、阻塞與非阻塞
阻塞:
當程序在執行過程中遇到了IO操作,此時進入阻塞狀態
非阻塞:
當程序正常執行代碼而沒有遇到IO操作時,此時就是非阻塞狀態
3、程序執行的三種狀態
在程序執行過程中,程序不是一直在執行的,那么程序在什么時候進行切換呢?
CPU切換一般分為兩種情況:
-
程序需要進行IO操作,程序進入阻塞狀態,CPU切換執行其他程序
-
程序執行時間過長,其時間片消耗完,CPU 切換執行其他程序
程序在執行過程中是在三種狀態之間不停的進行切換
這三種狀態分別是:執行態、就緒態、阻塞態
程序在被CPU執行時,進入執行態,當程序進行IO操作時,CPU切換執行其他程序,此時程序進入阻塞態,當程序的IO操作完成后,CPU不會立馬執行這個程序,而是程序進入就緒態,等待CPU的執行;當然CPU還有另一種切換的情況既程序執行時間過長,此時程序沒有進入阻塞態,而是直接進入就緒態,等待被CPU 執行
4、開啟進程的方法
進程的開啟與關閉時由操作系統進行的,那么我們如何開啟進程呢?
我們在開啟進程時,實際上不是在開啟進程,而是給系統發起一個指令,操作系統再根據我們的指令開啟進程,所以有時我們在開啟進程的過程中會發現,雖然發起了進程開啟的指令,但是還是會一小段時間后才能開啟成功
開啟進程的兩種方式:
直接將子進程執行的代碼作為參數傳入開啟的子進程
from multiprocessing import Process def test(name):print("子進程開啟")print(name)print("子進程結束") ? if __name__ == "__main__":print("父進程開啟")print(os.getpid())p = Process(target=test,args=("lee",))p.start()print("父進程結束")# 執行結果 # 父進程開啟 # 13254 # 父進程結束 # 子進程開啟 # lee # 子進程結束?
這種方式將需要執行的代碼直接作為參數傳遞給子進程,除此之外,還有另一種方法可以將需要子進程執行的代碼傳遞給子進程,那就是利用Process類將需要執行的代碼直接寫入到自己寫的Process的子類中
在上面的代碼中可以看到Process是一個類,那么我們就可以直接繼承自Process類,重寫其run方法就可以使子進程執行相應的程序
繼承Process方法重寫其run方法開啟子進程
from multiprocessing import Process ? class MyProcess(Process):def __init__(self, name):super().__init__()self.name = name ?def run(self):print("子進程開啟")print(self.name)print("子進程結束") ? ? if __name__ == "__main__":print("父進程開啟")p = MyProcess(name="rose")p.start()print("父進程結束")# 執行結果 #父進程開啟 # 父進程結束 # 子進程開啟 # rose # 子進程結束?
5、在Windows及liunx中使用開啟多進程的不同之處
在使用子進程執行程序時,子進程會首先copy父進程的部分數據,然后再將父進程的代碼導入到子進程中,此時如果不將父進程放入if __name__ == __main__中就會出現遞歸導入,導致程序報錯
但是在Linux中,開啟的子進程會完全復制父進程的代碼及記錄運行狀態,然后再進行執行,所以不會形成遞歸調用
當我們將程序交給子進程進行運行時,此時父進程與子進程之間的數據就是完全獨立的兩份,父進程的執行不會影響子進程中的變量,子進程的運行也不會影響父進程的變量
6、join方法
在使用父進程開啟了子進程后,如果父進程的執行需要等到子進程的執行結果,那么就需要讓父進程等待子進程的執行,但是當父進程執行較快時,子進程的執行還沒有完成,父進程就會結束,此時需要讓父進程等待子進程的執行,此時就需要使用join方法,join的作用就是提高子進程的優先級,使其執行完畢后才執行父進程
from multiprocessing import Process ?def run(name):print("子進程開啟")print(name)print("子進程結束") ? if __name__ == "__main__":print("父進程開啟")p = Process(target=run,args=("lee",))p.start()p.join()print("父進程結束")# 運行結果 # 父進程開始 # 子進程開始 # lee # 子進程結束 # 父進程結束?
?
7、多進程中的其它方法
name:進程的名字,在實例化進程對象時可以進行制定,如果不指定顯示的是Process-編號的形式
is_alive():判斷子進程是否仍存活
terminate():直接將子進程結束(殺死子進程)
pid:顯示子進程的進程編號
8、pid與ppid
pid:進程編號,指的是當前進程的進程號
ppid
?
9、僵尸進程與孤兒進程
僵尸進程:
當子進程執行結束而父進程還沒有結束時,系統會將子進程的資源進行回收,但是由于父進程需要查詢子進程的進程號等信息,所以不會將子進程的進程描述符清除,此時如果父進程不使用wait()或waitpid()查詢子進程,那么子進程會一直存在,產生僵尸進程,如果僵尸進程過多,那么就會占用系統的pid號,影響其他程序使用,不過在python中會對僵尸進程進行處理,不需要我們手動進行處理
當父進程已經結束,而子進程還沒有結束時,這時候子進程就稱之為孤兒進程,孤兒進程會交給系統進行處理,孤兒進程沒有危害
?
轉載于:https://www.cnblogs.com/lice-blog/p/10957453.html
總結
以上是生活随笔為你收集整理的day34 并行并发、进程开启、僵尸及孤儿进程的全部內容,希望文章能夠幫你解決所遇到的問題。