Day 31 并发编程
目錄
- 并發(fā)編程
- 并發(fā)和串行
- 學(xué)習(xí)并發(fā)的目的
- 進(jìn)程是什么
- 操作系統(tǒng)是什么
- 操作系統(tǒng)發(fā)展史
- 第二代計(jì)算使用的是批處理系統(tǒng),存在以下三個(gè)問(wèn)題
- 第三代計(jì)算機(jī)
- 第四代計(jì)算機(jī)
- 多道技術(shù)
- 并發(fā)編程中的重要概念
- python如何使用多進(jìn)程
- 1. 導(dǎo)入multiprocessing中的Process類(lèi) 實(shí)例化這個(gè)類(lèi) 指定要執(zhí)行的任務(wù)target
- 2. 導(dǎo)入multiprocessing中的Process類(lèi) 繼承這個(gè)類(lèi) 覆蓋run方法 將要執(zhí)行的任務(wù)放入run中開(kāi)啟進(jìn)程是會(huì)自動(dòng)執(zhí)行該函數(shù)
- 進(jìn)程之間內(nèi)存相互隔離
- join函數(shù)
- 進(jìn)程對(duì)象的常用屬性
- 僵尸進(jìn)程和孤兒進(jìn)程
并發(fā)編程
并發(fā)和串行
- 程序默認(rèn)的執(zhí)行方式是串行,即程序自上而下一行一行執(zhí)行,必須把當(dāng)前任務(wù)執(zhí)行完畢才能執(zhí)行下一個(gè)任務(wù)
學(xué)習(xí)并發(fā)的目的
就是編寫(xiě)可以同時(shí)執(zhí)行多個(gè)任務(wù)的程序,從而提高效率
串行和并發(fā)都是程序處理任務(wù)的方式
## 實(shí)現(xiàn)并發(fā)的方式
進(jìn)程是什么
進(jìn)程是指正在運(yùn)行的程序,是操作系統(tǒng)調(diào)度以及進(jìn)行資源分配的基本單位
當(dāng)程序從硬盤(pán)讀取到內(nèi)存中運(yùn)行的時(shí)候進(jìn)程就產(chǎn)生了
多進(jìn)程:指的是同一時(shí)間有多個(gè)程序被裝入內(nèi)存并執(zhí)行
多進(jìn)程的實(shí)現(xiàn)原理其實(shí)就是操作系統(tǒng)調(diào)度進(jìn)程的原理
操作系統(tǒng)是什么
操作系統(tǒng)就是一款特殊的軟件
操作系統(tǒng)和普通軟件的區(qū)別:
操作系統(tǒng)的主要功能
GUI圖形化用戶(hù)界面
操作系統(tǒng)發(fā)展史
掌握多道技術(shù)的實(shí)現(xiàn)原理,就是多進(jìn)程的實(shí)現(xiàn)原理
第二代計(jì)算使用的是批處理系統(tǒng),存在以下三個(gè)問(wèn)題
第三代計(jì)算機(jī)
使用SPOOLING聯(lián)機(jī)計(jì)數(shù)
多終端多用戶(hù)
第四代計(jì)算機(jī)
大規(guī)模集成電路+多用戶(hù)多終端
特點(diǎn):具備GUI圖形化界面,普通人也可以使用
多道技術(shù)
實(shí)現(xiàn)原理:
空間復(fù)用
? 同一時(shí)間加載多個(gè)任務(wù)到內(nèi)存中,多個(gè)進(jìn)程之間的內(nèi)存區(qū)域需要相互隔離,這種隔離是物理隔離,為了保證數(shù)據(jù)安全性
時(shí)間復(fù)用
? 操作系統(tǒng)會(huì)在多個(gè)進(jìn)程之間做切換
? 切換進(jìn)程的兩種情況:
? 1.但給一個(gè)進(jìn)程遇到IO操作時(shí)會(huì)自動(dòng)切換
? 2.當(dāng)任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)(超時(shí))強(qiáng)制切換
? 切換進(jìn)程前需要記錄當(dāng)前進(jìn)程的狀態(tài),同時(shí)頻繁的切換也消耗系統(tǒng)資源
? 當(dāng)所有任務(wù)沒(méi)有IO操作時(shí),切換執(zhí)行反而降低了效率,但是為了保證并發(fā)執(zhí)行必須要犧牲效率
多道技術(shù)總結(jié):切換+保存
有了多道技術(shù),計(jì)算機(jī)就可以同時(shí)并發(fā)處理多個(gè)任務(wù)
并發(fā)編程中的重要概念
串行:從上到下依次執(zhí)行
并發(fā):多個(gè)任務(wù)同時(shí)執(zhí)行,本質(zhì)是多個(gè)進(jìn)行不斷在切換,由于切換速度快,所以感覺(jué)是同時(shí)運(yùn)行
并行:真正意義上的同時(shí)運(yùn)行,有幾個(gè)核心就能并行幾個(gè)任務(wù),如果超過(guò)核心數(shù)就使用并發(fā)執(zhí)行
以上三個(gè)都是用于描述處理任務(wù)的方式
一個(gè)進(jìn)程的三種狀態(tài)
阻塞:當(dāng)程序遇到IO操作,無(wú)法繼續(xù)執(zhí)行代碼時(shí)的一種狀態(tài)
非阻塞 :程序沒(méi)有遇到IO操作的狀態(tài),正常運(yùn)行
就緒:程序等待CPU運(yùn)行
阻塞非阻塞也可以用來(lái)描述執(zhí)行任務(wù)的方式
三種狀態(tài)的互相切換
程序正常運(yùn)行,當(dāng)運(yùn)行時(shí)間超過(guò)閾值,會(huì)進(jìn)入就緒狀態(tài),等待cpu執(zhí)行完其他的進(jìn)程后,恢復(fù)到運(yùn)行狀態(tài)繼續(xù)執(zhí)行
當(dāng)程序遇到IO操作,會(huì)進(jìn)入阻塞狀態(tài),當(dāng)結(jié)束阻塞狀態(tài)后,程序會(huì)進(jìn)入就緒狀態(tài),等待cpu空閑后繼續(xù)執(zhí)行本程序
野指針和僵尸指針
野指針:內(nèi)存中的地址被刪除
僵尸指針:內(nèi)存中的地址因?yàn)槟撤N原因沒(méi)有被清除
進(jìn)程的創(chuàng)建和銷(xiāo)毀
創(chuàng)建:
銷(xiāo)毀:
進(jìn)程和程序
程序是一堆代碼存放在文件中
進(jìn)程就是程序中的代碼從硬盤(pán)讀入內(nèi)存后產(chǎn)生的
進(jìn)程是由程序產(chǎn)生的
一個(gè)程序可以產(chǎn)生多個(gè)進(jìn)程,每一個(gè)進(jìn)程都有一個(gè)唯一的PID
進(jìn)程的層次結(jié)構(gòu)
在linux中進(jìn)程具備父子關(guān)系,是一個(gè)樹(shù)狀結(jié)構(gòu),可以相互查找到對(duì)方
在windows中,沒(méi)有層級(jí)關(guān)系,父進(jìn)程可轉(zhuǎn)讓子進(jìn)程的句柄
父進(jìn)程與子進(jìn)程:例如qq打開(kāi)了瀏覽器,qq就是父進(jìn)程,瀏覽器就是子進(jìn)程
PID和PPID
PID是當(dāng)前進(jìn)程的編號(hào)
PPID是當(dāng)前程序的父進(jìn)程的編號(hào)
我們運(yùn)行py文件的時(shí)候其實(shí)是運(yùn)行python解釋器,所以運(yùn)行py文件的父進(jìn)程就是python解釋器
import os os.getpid() os.getppid()python如何使用多進(jìn)程
1. 導(dǎo)入multiprocessing中的Process類(lèi) 實(shí)例化這個(gè)類(lèi) 指定要執(zhí)行的任務(wù)target
import os from multiprocessing import Processdef task():print("this is sub process")print(f"sub process id {os.getpid()}" )if __name__ == '__main__':p = Process(target=task)p.start() print("this is parent process")print(f"parent process is: {os.getpid()}")print("over")linux和windows開(kāi)啟進(jìn)程的方式區(qū)別
linux會(huì)將父進(jìn)程的內(nèi)存數(shù)完整復(fù)制一份給子進(jìn)程
windows會(huì)導(dǎo)入父進(jìn)程的代碼,從新執(zhí)行一遍,來(lái)獲取需要處理的任務(wù),所以在編寫(xiě)代碼時(shí)如果是windows,需要把開(kāi)啟進(jìn)程的代碼放在main判斷中
2. 導(dǎo)入multiprocessing中的Process類(lèi) 繼承這個(gè)類(lèi) 覆蓋run方法 將要執(zhí)行的任務(wù)放入run中開(kāi)啟進(jìn)程是會(huì)自動(dòng)執(zhí)行該函數(shù)
from multiprocessing import Process import osclass Downloader(Process):def __init__(self,url,size,name):super().__init__()self.url = urlself.size = sizeself.name = namedef run(self):print(os.getpid())passif __name__ == '__main__':m = Downloader()m.start()print("parent over",os.getpid())進(jìn)程之間內(nèi)存相互隔離
from multiprocessing import Process import os,timea = 257def task():global aprint("2",a,id(a))a = 200if __name__ == '__main__':p = Process(target=task)p.start() time.sleep(4)print(a)join函數(shù)
就是讓主進(jìn)程等待子進(jìn)程運(yùn)行完再執(zhí)行
from multiprocessing import Process import timedef task1(name):for i in range(10000):print(f'{name} run')def task2(name):for i in range(100):print(f'{name} run')if __name__ == '__main__': p1 = Process(target=task1,args=("p1",))# args 是給子進(jìn)程傳遞的參數(shù) 必須是元組p1.start() p2 = Process(target=task2,args=("p2",))p2.start() p2.join() p1.join()print("over")進(jìn)程對(duì)象的常用屬性
if __name__ == '__main__':p = Process(target=task,name="老司機(jī)進(jìn)程")p.start()# p.join()# print(p.name)# p.daemon #守護(hù)進(jìn)程# p.join()# print(p.exitcode) # 獲取進(jìn)程的退出碼 就是exit()函數(shù)中傳入的值# print(p.is_alive()) # 查看進(jìn)程是否存活# print("zi",p.pid) # 獲取進(jìn)程id# print(os.getpid())# p.terminate() #終止進(jìn)程 與strat 相同的是 不會(huì)立即終止,因?yàn)椴僮飨到y(tǒng)有很多事情要做 # print(p.is_alive())僵尸進(jìn)程和孤兒進(jìn)程
孤兒進(jìn)程:當(dāng)父進(jìn)程已經(jīng)結(jié)束,而子進(jìn)程還在運(yùn)行,子進(jìn)程就成為孤兒進(jìn)程,孤兒進(jìn)程有其存在的意義,沒(méi)有不良影響,孤兒進(jìn)程會(huì)被操作系統(tǒng)接管
僵尸進(jìn)程:當(dāng)一個(gè)進(jìn)程已經(jīng)結(jié)束了,但是他仍然還有一些數(shù)據(jù)存在,此時(shí)稱(chēng)之為僵尸進(jìn)程
在linux中,有這么一個(gè)機(jī)制,父進(jìn)程無(wú)論什么時(shí)候都可以獲取到子進(jìn)程的一些數(shù)據(jù);子進(jìn)程任務(wù)執(zhí)行完畢后,確實(shí)結(jié)束了但是仍然保留了一些數(shù)據(jù),目的是為了讓父進(jìn)程能夠獲取這些信息;linux中,可以調(diào)用waitpid來(lái)徹底清除子進(jìn)程的殘留信息
python中已經(jīng)封裝了處理僵尸進(jìn)程的操作
轉(zhuǎn)載于:https://www.cnblogs.com/masterjian924/p/11124038.html
總結(jié)
以上是生活随笔為你收集整理的Day 31 并发编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 老雷socket编程之PHP利用sock
- 下一篇: nginx conf 文件