日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python_fullstack基础(十八)-并发编程

發(fā)布時間:2025/3/15 python 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python_fullstack基础(十八)-并发编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

并發(fā)編程

一、進程

1、理論背景

①操作系統(tǒng)背景

    • 手工操作—穿孔卡片?
      原理:用戶獨占計算機,CPU等待手工操作,資源利用和CPU利用效率極低
    • 批處理—磁帶處理、批處理系統(tǒng)?
      原理:主機與輸入機之間增加磁帶存儲設備,使得計算機可以自動將磁帶讀入計算機,成批完成作業(yè)?
      分類:脫機批處理系統(tǒng)、聯(lián)機批處理系統(tǒng)
    • 多道程序系統(tǒng)?
      原理:指允許多個程序同時進入內存并交替運行?
      特點:宏觀上并行、微觀上串行
    • 分時系統(tǒng)?
      原理:把處理機的運行時間分成很短的時間片,按時間片輪流把處理機分配給各聯(lián)機作業(yè)使用?
      特點:多路性、交互性、獨立性、及時性;在進行I/O切換的時候實際上效率相比下降低了
    • 實時系統(tǒng)?
      原理:程序獨占CPU,為了讓程序能夠及時響應隨機發(fā)生的外部事件,并在嚴格的時間范圍內完成對該事件的處理?
      分類:實時控制系統(tǒng)、實時信息處理系統(tǒng)?
      特點:及時響應、高可靠性。
    • 通用操作系統(tǒng)?
      定義:具有多種類型操作特征的操作系統(tǒng)。可以同時兼有多道批處理、分時、實時處理的功能,或其中兩種以上的功能。
    • 操作系統(tǒng)的進一步發(fā)展?
      分類:個人計算機操作系統(tǒng)、網(wǎng)絡操作系統(tǒng)、分布式操作系統(tǒng)
    • 操作系統(tǒng)的作用?
      作用:?
      • 1、隱藏了丑陋的硬件調用接口,為應用程序員提供調用硬件資源的更好,更簡單,更清晰的模型(系統(tǒng)調用接口)
      • 2、將應用程序對硬件資源的競態(tài)請求變得有序化

②何為進程、何為進程調度

  • 進程

狹義定義:進程是正在運行的程序的實例 廣義定義:進程是一個具有一定獨立功能的程序關于某個數(shù)據(jù)集合的一次運行活動 進程的意義:是操作系統(tǒng)動態(tài)執(zhí)行的基本單元,操傳統(tǒng)操作系統(tǒng)中,進程既是基本的分配單元,也是基本的執(zhí)行單元 操作系統(tǒng)引入進程的原因: 理論角度:是對正在運行的程序過程的抽象 實現(xiàn)角度:是一種數(shù)據(jù)結構,目的是描述動態(tài)系統(tǒng)的內在規(guī)律,有效管理、調度計算機系統(tǒng)主存儲器運行的程序

進程的特征:
動態(tài)性:進程的實質是程序在多道程序系統(tǒng)中的一次執(zhí)行過程,進程是動態(tài)產生,動態(tài)消亡的。 并發(fā)性:任何進程都可以同其他進程一起并發(fā)執(zhí)行 獨立性:進程是一個能獨立運行的基本單位,同時也是系統(tǒng)分配資源和調度的獨立單位; 異步性:由于進程間的相互制約,使進程具有執(zhí)行的間斷性,即進程按各自獨立的、不可預知的速度向前推進 結構特征:進程由程序、數(shù)據(jù)和進程控制塊三部分組成。 多個不同的進程可以包含相同的程序:一個程序在不同的數(shù)據(jù)集里就構成不同的進程,能得到不同的結果;但是執(zhí)行過程中,程序不能發(fā)生改變。

進程與程序的區(qū)別:

程序是指令和數(shù)據(jù)的有序集合,其本身沒有任何運行的含義,是一個靜態(tài)的概念。 而進程是程序在處理機上的一次執(zhí)行過程,它是一個動態(tài)的概念。 程序可以作為一種軟件資料長期存在,而進程是有一定生命期的。 程序是永久的,進程是暫時的。

?進程調度

    • 先來先服務調度算法:?
      先來先服務(FCFS)調度算法是一種最簡單的調度算法,該算法既可用于作業(yè)調度,也可用于進程調度。FCFS算法比較有利于長作業(yè)(進程),而不利于短作業(yè)(進程)。由此可知,本算法適合于CPU繁忙型作業(yè),而不利于I/O繁忙型的作業(yè)(進程)。

    • 短作業(yè)優(yōu)先調度算法:?
      短作業(yè)(進程)優(yōu)先調度算法(SJ/PF)是指對短作業(yè)或短進程優(yōu)先調度的算法,該算法既可用于作業(yè)調度,也可用于進程調度。但其對長作業(yè)不利;不能保證緊迫性作業(yè)(進程)被及時處理;作業(yè)的長短只是被估算出來的。

    • 時間片輪轉法:?
      時間片輪轉(Round Robin,RR)法的基本思路是讓每個進程在就緒隊列中的等待時間與享受服務的時間成比例。在時間片輪轉法中,需要將CPU的處理時間分成固定大小的時間片,如果一個進程在被調度選中之后用完了系統(tǒng)規(guī)定的時間片,但又未完成要求的任務,則它自行釋放自己所占有的CPU而排到就緒隊列的末尾,等待下一次調度。同時,進程調度程序又去調度當前就緒隊列中的第一個進程。

    • 多級反饋隊列:?
      應設置多個就緒隊列,并為各個隊列賦予不同的優(yōu)先級。當一個新進程進入內存后,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調度。當輪到該進程執(zhí)行時,如它能在該時間片內完成,便可準備撤離系統(tǒng);如果它在一個時間片結束時尚未完成,調度程序便將該進程轉入第二隊列的末尾按照FCFS原則等待調度執(zhí)行,以此類推,而且僅當?shù)谝魂犃锌臻e時,調度程序才調度第二隊列中的進程運行

③進程的并發(fā)、并行

  • 并行:是指兩者同時執(zhí)行
  • 并發(fā):是指資源有限的情況下,兩者交替輪流使用資源,以便提高效率
  • 區(qū)別:并行是從微觀上,也就是在一個精確的時間片刻,有不同的程序在執(zhí)行,這就要求必須有多個處理器;并發(fā)是從宏觀上,在一個時間段上可以看出是同時執(zhí)行的,比如一個服務器同時處理多個session。?
  • ?

④同步、異步、阻塞、非阻塞

  • 同步:?
    系統(tǒng)功能調用時,在沒有得到結果之前,該調用就不會返回。按照這個定義,其實絕大多數(shù)函數(shù)都是同步調用。但是一般而言,我們在說同步、異步的時候,特指那些需要其他部件協(xié)作或者需要一定時間完成的任務。

  • 異步:?
    異步的概念和同步相對。當一個異步功能調用發(fā)出后,調用者不能立刻得到結果。當該異步功能完成后,通過狀態(tài)、通知或回調來通知調用者。如果異步功能用狀態(tài)來通知,那么調用者就需要每隔一定時間檢查一次,效率就很低(有些初學多線程編程的人,總喜歡用一個循環(huán)去檢查某個變量的值,這其實是一 種很嚴重的錯誤)。如果是使用通知的方式,效率則很高,因為異步功能幾乎不需要做額外的操作。至于回調函數(shù),其實和通知沒太多區(qū)別。

  • 阻塞:?
    阻塞調用是指調用結果返回之前,當前線程會被掛起(如遇到io操作)。函數(shù)只有在得到結果之后才會將阻塞的線程激活。有人也許會把阻塞調用和同步調用等同起來,實際上他是不同的。對于同步調用來說,很多時候當前線程還是激活的,只是從邏輯上當前函數(shù)沒有返回而已。

  • 非阻塞:?
    非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前也會立刻返回,同時該函數(shù)不會阻塞當前線程。

  • 總結:

    • 同步與異步針對的是函數(shù)/任務的調用方式:同步就是當一個進程發(fā)起一個函數(shù)(任務)調用的時候,一直等到函數(shù)(任務)完成,而進程繼續(xù)處于激活狀態(tài)。而異步情況下是當一個進程發(fā)起一個函數(shù)(任務)調用的時候,不會等函數(shù)返回,而是繼續(xù)往下執(zhí)行當,函數(shù)返回的時候通過狀態(tài)、通知、事件等方式通知進程任務完成。
    • 阻塞與非阻塞針對的是進程或線程:阻塞是當請求不能滿足的時候就將進程掛起,而非阻塞則不會阻塞當前進程
  • 同步阻塞形式:?
    效率最低。一直等待進程結束,其他什么也不做

  • 異步阻塞形式:?
    異步操作是可以被阻塞住的,只不過它不是在處理消息時阻塞,而是在等待消息通知時被阻塞

  • 同步非阻塞形式:?
    實際上是效率低下的,因為程序需要在這兩種不同的行為之間來回的切換,效率浪費在了程序切換中

  • 異步非阻塞形式:?
    效率較高,程序沒有在兩種不同的操作中來回切換

  • 總結:?
    同步和阻塞混淆很容易混淆,因為很多時候同步操作會以阻塞的形式表現(xiàn)出來,同樣很多人也會把異步和非阻塞混淆,因為異步操作一般都不會在真正的I/O操作處被阻塞。

⑤進程的創(chuàng)建、結束(了解)

  • 進程的創(chuàng)建的4種形式:

    • 系統(tǒng)初始化(查看進程linux中用ps命令,windows中用任務管理器,前臺進程負責與用戶交互,后臺運行的進程與用戶無關,運行在后臺并且只在需要時才喚醒的進程,稱為守護進程,如電子郵件、web頁面、新聞、打印)
    • 一個進程在運行過程中開啟了子進程(如nginx開啟多進程,os.fork,subprocess.Popen等)
    • 用戶的交互式請求,而創(chuàng)建一個新進程(用戶雙擊操作)
    • 一個批處理作業(yè)的初始化(只在大型機的批處理系統(tǒng)中應用)
  • 進程的結束

    • 正常退出(自愿,如用戶點擊交互式頁面的叉號,或程序執(zhí)行完畢調用發(fā)起系統(tǒng)調用正常退出,在linux中用exit,在windows中用ExitProcess)
    • 出錯退出(自愿,python a.py中a.py不存在)
    • 嚴重錯誤(非自愿,執(zhí)行非法指令,如引用不存在的內存,I/O等,可以捕捉異常,try…except…)
    • 被其他進程殺死(非自愿,如kill -9 PID)

2、python中的進程應用——multiprocessing模塊

①multiprocessing模塊簡介:

multiprocess不是一個模塊而是python中一個操作、管理進程的包,這個包中幾乎包含了和進程有關的所有子模塊。以下將分為:進程創(chuàng)建部分、進程同步部分、進程間通信部分、進程池部分和進程之間數(shù)據(jù)共享來介紹

②進程創(chuàng)建部分

    • process模塊語法簡介?
      Process([group [, target [, name [, args [, kwargs]]]]]),由該類實例化得到的對象,表示一個子進程中的任務(尚未啟動)

      • 強調:

需要使用關鍵字的方式來指定參數(shù) args指定的為傳給target函數(shù)的位置參數(shù),是一個元組形式,必須有逗號

參數(shù)介紹:

group參數(shù)未使用,值始終為None target表示調用對象,即子進程要執(zhí)行的任務 args表示調用對象的位置參數(shù)元組,args=(1,2,’yang’,) kwargs表示調用對象的字典,kwargs={‘name’:’yang’,’age’:18} name為子進程的名稱

子進程常用方法

p.start():啟動進程,并調用該子進程中的p.run() p.run():進程啟動時運行的方法,正是它去調用target指定的函數(shù),我們自定義類的類中一定要實現(xiàn)該方法 p.terminate():強制終止進程p,不會進行任何清理操作,如果p創(chuàng)建了子進程,該子進程就成了僵尸進程,使用該方法需要特別小心這種情況。如果p還保存了一個鎖那么也將不會被釋放,進而導致死鎖 p.is_alive():如果p仍然運行,返回True p.join([timeout]):主線程等待p終止(強調:是主線程處于等的狀態(tài),而p是處于運行的狀態(tài))。timeout是可選的超時時間,需要強調的是,p.join只能join住start開啟的進程,而不能join住run開啟的進程 p.daemon:默認值為False,如果設為True,代表p為后臺運行的守護進程,當p的父進程終止時,p也隨之終止,并且設定為True后,p不能創(chuàng)建自己的新進程,必須在p.start()之前設置 p.name:進程的名稱 p.pid:進程的pid p.exitcode:進程在運行時為None、如果為–N,表示被信號N結束(了解即可) p.authkey:進程的身份驗證鍵,默認是由os.urandom()隨機生成的32字符的字符串。這個鍵的用途是為涉及網(wǎng)絡連接的底層進程間通信提供安全性,這類連接只有在具有相同的身份驗證鍵時才能成功(了解即可)
    • tips?
      在Windows操作系統(tǒng)中由于沒有fork(linux操作系統(tǒng)中創(chuàng)建進程的機制),在創(chuàng)建子進程的時候會自動 import 啟動它的這個文件,而在import的時候又執(zhí)行了整個文件。因此如果將process()直接寫在文件中就會無限遞歸創(chuàng)建子進程報錯。所以必須把創(chuàng)建子進程的部分使用if __name__ ==‘__main__’ 判斷保護起來,import 的時候,就不會遞歸運行了。

    • 面向函數(shù)——創(chuàng)建子進程實現(xiàn)并發(fā)

import os from multiprocessing import Processdef func():print('this is subprocess:{}'.format(os.getpid()))if __name__ == '__main__':p = Process(target=func,args=())p.start()print('this is parent_process:{}'.format(os.getpid()))
  • 面向函數(shù)——創(chuàng)建多個子進程
import os from multiprocessing import Processdef func(i):print('{}、this is subprocess:{},father:{}'.format(i,os.getpid(), os.getppid()))if __name__ == '__main__':for i in range(5):p = Process(target=func, args=(i+1,))p.start()print('this is parent_process:{}'.format(os.getpid()))
  • 面向函數(shù)——多個進程同時運行
import os import time from multiprocessing import Processdef func(i):time.sleep(0.1)print('{}、this is subprocess:{},father:{}'.format(i,os.getpid(), os.getppid()))if __name__ == '__main__':p_lst = []for i in range(5):p = Process(target=func, args=(i+1,))p.start()p_lst.append(p)[j.join() for j in p_lst]print('this is parent_process:{}'.format(os.getpid()))
  • 面向對象——創(chuàng)建進程
import os from multiprocessing import Processclass MyProcess(Process):def __init__(self, something):super().__init__()self.something = somethingdef run(self):print('this is subprocess:{}'.format(os.getpid()), self.something)if __name__ == '__main__':p1 = MyProcess('我是參數(shù)')p2 = MyProcess('我是參數(shù)')p1.start()p2.start()p1.join()p2.join()print('this is parent_process:{}'.format(os.getpid()))
  • 進程間數(shù)據(jù)隔離問題
from multiprocessing import Processdef work():global nn=0print('子進程內: ',n)if __name__ == '__main__':n = 100p=Process(target=work)p.start()print('主進程內: ',n)
  • 守護進程:會隨著主進程的結束而結束?
    主進程創(chuàng)建守護進程?
    其一:守護進程會在主進程代碼執(zhí)行結束后就終止?
    其二:守護進程內無法再開啟子進程,否則拋出AssertionError異常?
    注意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止

③進程同步部分(multiprocess.Lock、multiprocess.Semaphore、multiprocess.Event)

    • 鎖multiprocess.Lock

      • 加鎖可以保證多個進程修改同一塊數(shù)據(jù)時,同時刻只能有一個任務可以進行修改,即串行的修改,這樣做雖然犧牲了速度卻保證了數(shù)據(jù)安全。所以可以mutiprocessing模塊為我們提供更好的的基于消息的IPC通信機制:隊列和管道

      • 應用實例

def search(i):with open('ticket', mode='r', encoding='utf-8') as f:print(i, '剩余票數(shù):{}'.format(json.load(f)['ticket_num']))def get(i):with open('ticket', mode='r', encoding='utf-8') as f:num = json.load(f)['ticket_num']time.sleep(random.random())if num > 0:with open('ticket', mode='w', encoding='utf-8') as f_w:json.dump({'ticket_num': num - 1}, f_w)print('{}:買到票了!'.format(i))else:print('{}:沒有買到票!'.format(i))def task(i, lock):search(i)lock.acquire()get(i)lock.release()if __name__ == '__main__':with open('ticket',mode='w') as f_1:json.dump({'ticket_num': 5}, f_1)lock = Lock()for i in range(10):p = Process(target=task, args=(i, lock,))p.start()

信號量multiprocess.Semaphore

  • 介紹:互斥鎖同時只允許一個線程更改數(shù)據(jù),而信號量Semaphore是同時允許一定數(shù)量的線程更改數(shù)據(jù)

  • 注意:信號量同步基于內部計數(shù)器,每調用一次acquire(),計數(shù)器減1;每調用一次release(),計數(shù)器加1;當計數(shù)器為0時,acquire()調用被阻塞。這是迪科斯徹(Dijkstra)信號量概念P()和V()的Python實現(xiàn)。信號量同步機制適用于訪問像服務器這樣的有限資源。信號量與進程池的概念很像,但是要區(qū)分開,信號量涉及到加鎖的概念。

  • 應用實例

def sing(i,sem):sem.acquire()print('{}:進入>>>>'.format(i))time.sleep(random.randint(1,3))print('{}:<<<<出'.format(i))sem.release()if __name__ == '__main__':sem = Semaphore(4)for i in range(10):p = Process(target=sing,args=(i,sem))p.start()

事件multiprocess.Event

  • 介紹:

事件用于主線程控制其他線程的執(zhí)行,事件主要提供了三個方法 e.set()、e.wait()、e.clear()、e.is_set()事件處理的機制:全局定義了一個“Flag”,如果“Flag”值為 False,那么當程序執(zhí)行
event.wait 方法時就會阻塞,如果“Flag”值為True,那么event.wait 方法時便不再阻塞。 clear:將“Flag”設置為False set:將“Flag”設置為True

應用實例

def traffic_light(e):while True:if e.is_set():time.sleep(1)print('紅燈亮')e.clear()else:time.sleep(1)print('綠燈亮')e.set()def car(i, e):e.wait()print('{}:車通過...'.format(i))if __name__ == '__main__':e = Event()traffic = Process(target=traffic_light, args=(e,))traffic.daemon = Truetraffic.start()for i in range(30):if i % 6:time.sleep(random.random())car_obj = Process(target=car, args=(i, e))car_obj.start()

④進程間通信部分(multiprocess.Queue、multiprocess.Pipe)

  • 進程間通信:IPC(Inter-Process Communication)
  • 隊列multiprocess.Queue

    • 介紹:創(chuàng)建共享的進程隊列,Queue是多進程安全的隊列,可以使用Queue實現(xiàn)多進程之間的數(shù)據(jù)傳遞。
    • 語法:

    • Queue([maxsize]) :創(chuàng)建共享的進程隊列參數(shù) :maxsize是隊列中允許的最大項數(shù)。如果省略此參數(shù),則無大小限制。(底層隊列使用管道和鎖定實現(xiàn))

      ?

Queue的實例q具有以下方法:

q.get( [ block [ ,timeout ] ] )返回q中的一個項目。如果q為空,此方法將阻塞,直到隊列中有項目可用為止。block用于控制阻塞行為,默認為True. 如果設置為False,將引發(fā)Queue.Empty異常(定義在Queue模塊中)。timeout是可選超時時間,用在阻塞模式中。如果在制定的時間間隔內沒有項目變?yōu)榭捎?#xff0c;將引發(fā)Queue.Empty異常。 q.get_nowait( )同q.get(False)方法。 q.put(item [, block [,timeout ] ] )將item放入隊列。如果隊列已滿,此方法將阻塞至有空間可用為止。block控制阻塞行為,默認為True。如果設置為False,將引發(fā)Queue.Empty異常(定義在Queue庫模塊中)。timeout指定在阻塞模式中等待可用空間的時間長短。超時后將引發(fā)Queue.Full異常。 q.qsize()返回隊列中目前項目的正確數(shù)量。此函數(shù)的結果并不可靠,因為在返回結果和在稍后程序中使用結果之間,隊列中可能添加或刪除了項目。在某些系統(tǒng)上,此方法可能引發(fā)NotImplementedError異常。 q.empty()如果調用此方法時 q為空,返回True。如果其他進程或線程正在往隊列中添加項目,結果是不可靠的。也就是說,在返回和使用結果之間,隊列中可能已經(jīng)加入新的項目。 q.full()如果q已滿,返回為True. 由于線程的存在,結果也可能是不可靠的(參考q.empty()方法)
  • 管道m(xù)ultiprocess.Pipe

⑤進程池部分

⑥進程之間數(shù)據(jù)共享

?

轉載于:https://www.cnblogs.com/lidaxu/p/8407011.html

總結

以上是生活随笔為你收集整理的python_fullstack基础(十八)-并发编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。