python中的多進程和多線程

what?

進程和線程的概念:

   進程是資源佔用的最小單位 

   線程是內核調度執行的最小單位


進程和線程的主要區別:

   進程之間是彼此獨立的,由master進程通過fork()系統調用派生子進程

   線程是共享內存空間的,主線程派生子線程


why?

進程和線程的優缺點:

   進程:

     優點:進程由於各自有獨立的內存空間,所以更加穩定,子進程之間不受影響,但是主進程崩潰會導致全局,而且在python中不受GIL(全局解釋器鎖)限制,可以充分利用多核cpu

     缺點:對於內存資源佔用比較高,而且創建一個進程的代價比線程要大

   線程:

     優點:由於共享內存空間,所以資源佔用比較小,並且創建的代價小於進程,在python中受到GIL的限制,導致只能使用一個cpu核心,所以某一時刻運行的線程只有一個

     缺點:由於共享內存空間也導致了缺點,資源徵用的問題(python中可以通過鎖的機制限制),並且一個線程的崩潰可能導致整個進程崩潰


fork()系統調用:

   是unix/linux上比較特殊的一個系統調用,用於創建子進程,其特殊之處在於其他的系統調用函數一般調用一次返回一次,fork()調用一個返回兩次(父進程pid+子進程pid),且fork()調用時返回的子進程pid永遠爲0


where?(python中考慮)

多進程和多線程的共同目標是實現多任務

任務類型:cpu密集型和io密集型

   cpu密集型:應該使用多進程,充分利用多核cpu實現真正意義上的併發執行

   io密集型:可以使用多線程,節約資源


how?

 在python中怎樣使用多進程和多線程編程?

  1. 多線程

    python對於多線程的支持提供了兩個基礎庫,較爲底層的thread模塊和較爲高層的threading模塊

    實現原理:

     將準備併發執行的代碼當做參數傳遞給threading.Thread()創建一個線程對象,結合程序控制結構(循環)等方式來完成此線程對象start()的多次調用,從而實現多線程

     示例代碼:(利用多線程實現併發socket通信服務端)

      import threading  ##導入線程庫

      import socket    ##導入socket

      s=socket.socket()   #創建socket對象

      s.bind(('0.0.0.0',8888))   #綁定套接字

      s.listen(10)         #監聽套接字

      def run():            #定義處理函數

         sock,addr=s.accept()

         while True:

             a=sock.recv(1024)

             if a:

                sock.send(a.upper())

             else:

                sock.close()

                break

      if __name__ =='__main__':

         for i in xrange(20):    #根據for循環創建20個線程

             t=threading.Thread(target=run)   #創建線程對象

             t.start()    #運行線程

      

      此示例的第二種寫法:

      import threading  ##導入線程庫

      import socket    ##導入socket

      s=socket.socket()   #創建socket對象

      s.bind(('0.0.0.0',8888))   #綁定套接字

      s.listen(10)         #監聽套接字

      class Mythread(threading.Thread): 

          def run(self):            #定義處理函數

             sock,addr=s.accept()

             while True:

                 a=sock.recv(1024)

                 if a:

                    sock.send(a.upper())

                 else:

                    sock.close()

                    break

      if __name__ =='__main__':

         for i in xrange(20):    #根據for循環創建20個線程

             t=Mythread()   #創建線程對象

             t.start()    #運行線程

      

2.多進程

   python提供可multiprocessing模塊中的Process類來創建進程對象,同時該模塊還提供了Pool類來創建進程池對象,以及Queue和Pipe實現進程間通信

   實現原理:

      將準備併發執行的代碼當做參數傳遞給multiprocessing.Process()創建一個進程對象,結合程序控制結構(循環)等方式來完成此進程對象start()的多次調用,從而實現多進程 

      示例代碼:(利用多進程實現併發socket通信服務端)    

     

     import multiprocessing  ##導入線程庫

      import socket    ##導入socket

      s=socket.socket()   #創建socket對象

      s.bind(('0.0.0.0',8888))   #綁定套接字

      s.listen(10)         #監聽套接字

      def run():            #定義處理函數

         sock,addr=s.accept()

         while True:

             a=sock.recv(1024)

             if a:

                sock.send(a.upper())

             else:

                sock.close()

                break

      if __name__ =='__main__':

         for i in xrange(20):    #根據for循環創建20個線程

             t=multiprocess.Process(target=run)   #創建線程對象

             t.start()    #運行線程

 //可以使用ps aux | grep python 查看已經運行了20個進程

     同上:也可以自定義類並繼承Process類再實例化對象的方式進行編寫



總結:對於多任務的情形,併發是不可避免的問題,多進程和多線程可以實現併發,但是由於其都有不可避免的缺陷,所以如何讓單進程或單線程實現併發任務的處理,如nginx,就需要使用異步IO的機制,基於事件驅動,在python中實現此機制的稱爲協程。

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章