1. 程式人生 > 實用技巧 >python 網路併發 :理論部分

python 網路併發 :理論部分

1.今日內容大綱

  1. 程序的介紹(理論部分)

  2. 程序的建立以及分析

  3. 獲取程序的pid

  4. 程序之間的隔離

1.程序的介紹(理論部分)

1.1什麼是程序

一個正在被cpu執行的程式就是一個程序,一個程式可以開啟多個程序。

1.2 序列、併發、並行

1.2.1 序列

程式一個一個的被執行,同一時刻cpu只能執行一個程式。

1.2.2 並行

並行是同時執行多個程式,一個cpu執行一個程式,如果4個cpu同時執行4個程式。

1.2.3 併發

偽並行,看起來像是同時執行,其實是cpu在不同的任務間來回切換。多道技術。

  • 誰的效率最高?

    並行的效率最高。

  • 除去並行,直說序列和併發,誰的效率高?

    如果多個任務都是計算密集型,序列的效率高。

    如果IO密集型的任務居多,併發的效率高。

1.3 阻塞、非阻塞

  • 阻塞

    程式執行中由於某種原因(input,accept等)使得程式夯住,等待一段時間之後(獲取到了結果之後),再繼續執行。如果阻塞了,作業系統會將cpu從此任務中切換到執行其他的任務。

  • 非阻塞

    程式執行開始至結束中途無需等待結果(停住)。

1.4 程序的建立

無論哪一種,新程序的建立都是由一個已經存在的程序執行了一個用於建立程序的系統呼叫而建立的:(言外之意,一個程序的建立一定是基於一個父程序)

  • 在UNIX中該系統呼叫是:fork,fork會建立一個與父程序一模一樣的副本,二者有相同的儲存映像、同樣的環境字串和同樣的開啟檔案(在shell直譯器程序中,執行一個命令就會建立一個子程序)

  • 在windows中該系統呼叫是:CreateProcess,CreateProcess既處理程序的建立,也負責把正確的程式裝入新程序。

關於建立的子程序,UNIX和windows

相同的是:程序建立後,父程序和子程序有各自不同的地址空間(多道技術要求物理層面實現程序之間記憶體的隔離),任何一個程序的在其地址空間中的修改都不會影響到另外一個程序。

不同的是:在UNIX中,子程序的初始地址空間是父程序的一個副本,提示:子程序和父程序是可以有隻讀的共享記憶體區的。但是對於windows系統來說,從一開始父程序與子程序的地址空間就是不同的。

1.5 程序的三個狀態

程序的三個狀態:執行,阻塞,就緒。

2.python的併發程式設計之多程序

2.1建立程序的兩種方式

  • 引子

    我們之前寫的那些專案,模擬部落格園,ATM,教務管理系統等等都是一個程式,只有socket才是開啟了多個程序進行操作。

  • 函式式開啟程序的方式

    from multiprocessing import Process


    def task(a):
    print('in task')
    return a + 1


    if __name__ == '__main__': # windows系統下,開啟多程序一定要配置這行程式碼。

    p1 = Process(target=task, args=(100,)) # 建立一個子程序物件
    p1.start() # 通知作業系統在記憶體中開闢一個子程序空間,將主程序所有的資源深copy一份放置到子程序空間中
    print('=====主')



    # import time
    # a = 1
    # b = 2
    # print(a + b)
    # time.sleep(2)
    # print(666)
    • 為什麼主程序先執行,而子程序後執行?

      當p.start執行時,記憶體中馬上開闢一個空間,建立一個子程序,此時cpu對應的就是在主子程序之間選擇切換,由於子程序還需要載入資料等,遇到了阻塞,所以先執行主程序,這也說明了開啟程序的開銷相對較大。

  • 面向物件開啟程序方式

    # from multiprocessing import Process
    # import time
    #
    # def task(a):
    # print('in task')
    # return a + 1
    #
    #
    # if __name__ == '__main__': # windows系統下,開啟多程序一定要配置這行程式碼。
    #
    # p1 = Process(target=task, args=(100,)) # 建立一個子程序物件
    # p1.start() # 通知作業系統在記憶體中開闢一個子程序空間,將主程序所有的資源深copy一份放置到子程序空間中
    # time.sleep(1)
    # print('=====主')



    # import time
    # a = 1
    # b = 2
    # print(a + b)
    # time.sleep(2)
    # print(666)


    from multiprocessing import Process
    import time

    class MyProcess(Process):

    def __init__(self, name):
    super().__init__()
    self.name = name

    def run(self): # 子程序的任務
    print(f'{self.name}開始運行了')
    time.sleep(2)
    print(f'{self.name}子程序結束了')


    if __name__ == '__main__':

    p1 = MyProcess('瑋哥')
    p1.start()
    time.sleep(1)
    print('=====主')

    注意:在windows中Process()必須放到# if name == 'main':下

    Since Windows has no fork, the multiprocessing module starts a new Python process and imports the calling module. 
    If Process() gets called upon import, then this sets off an infinite succession of new processes (or until your machine runs out of resources).
    This is the reason for hiding calls to Process() inside

    if __name__ == "__main__"
    since statements inside this if-statement will not get called upon import.
    由於Windows沒有fork,多處理模組啟動一個新的Python程序並匯入呼叫模組。
    如果在匯入時呼叫Process(),那麼這將啟動無限繼承的新程序(或直到機器耗盡資源)。
    這是隱藏對Process()內部呼叫的原,使用if __name__ == “__main __”,這個if語句中的語句將不會在匯入時被呼叫。

    詳細解釋