進程(代碼)

  multiprocessing, 不是一個模塊, 而是python中一個操做, 管理進程的包, 在這個包中幾乎包含了和進程有關的全部子模塊.python

  大體能夠分爲四個部分: 建立進程, 進程同步, 進程池, 進程之間數據共享.編程

  強調: 進程沒有任何共享狀態, 進程修改的數據, 僅限於進程內部, 可是經過一些特殊的方法能夠實現進程之間數據的共享.安全

1. Process模塊介紹:併發

  Process模塊是一個建立進程的模塊, 藉助這個模塊能夠完成進程的建立.異步

  在Windows下執行程序的時候, 要加上 if __name__ == "__main__":  不然會出現子進程中運次的時候還開啓子進程, 出現無限循環的建立進程, 會報錯.函數

  Process中的參數介紹:spa

    target 表示調用對象, 即子進程要執行的任務;操作系統

    args 表示調用對象的位置參數元組, args = (1, 2, )對象

    kwargs 表示調用對象的字典, kwargs = {"name": alex}繼承

    name爲子進程的名稱

  Process中各方法的介紹:

    p.start() 啓動程序, 並調用該子進程的p.run()

    p.run() 進程啓動時運行的方法, 它去調用target指定的函數, 咱們自定義的類中必定要實現這個方法

    p.terminate() 強制終止進程p, 不會進行任何清理操做, 若是p建立了子進程, 該子進程就成了殭屍進程, 使用該方法時須要特別當心, 若是p保存了一個鎖那麼也將不會被釋放, 進而致使死鎖.

    p.is_alive() 若p還在運行, 則返回True

    p.join() 主進程等待p終止, 主進程處於等的狀態, 子進程p處於運行的狀態, p.join只能join住start開啓的進程, 而不能join住run開啓的進程

      join 例子: 讓主進程加上join的地方等待, 也就是阻塞住, 等待子進程執行完以後, 再繼續往下執行主進程, 當主進程須要子進程的執行結果是, 就要等待. join感受就是將子進程和主進程拼接起來, 將異步改成同步執行. 當須要全部的子進程異步執行, 而後全部的子進程所有執行完後再執行主進程時, 能夠join和for循環一塊兒使用.

  Process中自帶封裝的屬性介紹:

    p.daemon: 默認值爲False, 若是設爲True, 表明p爲後臺運行的守護進程, 當p的父進程終止時, p也隨之終止, 並且設置爲True後, p不能建立本身的新進程, 必須在p.start()以前設置.

    p.name: 進程的名稱

    p.pid: 進程的id

2. Process的使用:

  注意: 在Windows中, Process()必須放到  if __name__ == "__main__": 下

  進程的建立第二種方法(繼承): 自定義一個類, 繼承Process, 必需要有run方法, 經過__init__能夠傳參數, 可是須要super.__init__().

  進程之間的內存空間是隔離的, 即數據不共享.

  Process的其餘方法或屬性:

    p.terminate() 關閉進程, 不會當即關閉, 有個等待操做系統關閉這個進程的時間, 全部is_alive馬上查看的結果可能仍是存活的

3. 守護進程:

  守護進程會在主進程代碼執行結束後就終止

  守護進程內沒法再開啓子進程, 不然會拋出異常, 

  進程之間是互相獨立的, 主進程代碼運行結束, 守護進程隨即終止.

  p.daemon = True   必定要在p.start()以前設置

4. 進程同步(鎖):

  雖然併發編程能更加充分的利用IO資源, 可是也帶來了新的問題: 進程之間的數據不共享, 可是共享同一個文件系統, 因此訪問同一個文件, 或同一個打印終端時是沒有問題的, 可是共享帶來了競爭, 而競爭帶來的結果就是錯亂, 爲了加以控制, 進行加鎖處理.

  加鎖, 保證每次只有一個進程在執行鎖裏面的程序, 由併發變成了串行, 犧牲了運行效率, 可是避免了競爭. 解鎖以後, 其餘進程才能去執行本身的程序.

5. 隊列:

  進程彼此之間互相隔離, 要實現進程之間的通訊, 可使用隊列和管道, 這兩個方式都是使用消息傳遞的, 隊列就像一個特殊的列表, 能夠設置固定長度, 先進先出.

  方法介紹:

    q = Queue(maxsize)  建立共享的進程隊列, maxsize是長度

    q.get()  返回隊列中的一個數據, 若是隊列爲空, 則會阻塞, 直到隊列中有數據爲止.

    q.get(False)   同get 可是若是隊列爲空, 不會阻塞

    q.get_nowait()  同get(False)

    q.put()  向隊列裏放數據, 若是隊裏已滿, 會阻塞, 直到有空間可用

    q.qsize()  返回隊列中當前數據的數量

    q.empty()  判斷隊列是否爲空, 結果不可靠

    q.full 判斷隊列是否已滿, 結果也是不可靠的

  隊列裏的數據是安全的, 同一時間只能一個進程拿到隊列中的一個數據.

6. 生產者消費者模型

  生產者消費者模式是經過一個容器來解決生產者和消費者的強耦合問題. 生產者和消費者之間不直接通信, 而是經過阻塞隊列來進行通信, 因此生產者生產完數據以後不用等待消費者處理, 而是直接扔給阻塞隊列, 消費者不找生產者要數據, 而是直接從阻塞隊列裏取, 阻塞隊列就至關於一個緩衝區, 平衡生產者和消費者的處理能力, 而且能夠根據生產速度和消費速度來均衡一下多少生產者能夠爲多少個消費者提供足夠的服務, 能夠開多進程, 而這些進程都是到阻塞隊列中去獲取或者添加數據.

  程序中有兩類角色: 負責生產數據的生產者, 負責處理數據的消費者

  引入生產者消費者模型的目的: 平衡生產者與消費者之間的工做能力, 從而提升程序總體處理數據的速度

  具體實現: 生產者 <--->隊列<--->消費者

  發送結束信號None的兩種方式:  子進程生產者在生產完畢後發送結束信號None

                  主進程在生產者生產完畢後發送結束信號None

7. JoinableQueue([maxsize])

  相似一個Queue對象, 但隊列容許項目的使用者通知生產者項目已經被成功處理, 通知進程是使用共享的信號和條件變量來實現的.

  maxsize參數: 是隊列中容許的最大項數, 省略則無大小限制

  方法介紹: 

    q.task_done(): 使用者使用此方法發出信號, 表示q.get()的返回項目已經被處理, 若是調用此方法的次數大於從隊列中刪除項目的數量, 將引起異常

    q.join(): 生產者調用此方法進行阻塞, 直到隊列中全部的項目都被處理, 阻塞將持續到隊列中的每一個項目均調用q.task_done()方法.

相關文章
相關標籤/搜索