我們先來了解什么是進程?
程序并不能單獨運行,只有將程序裝載到內存中,系統為它分配資源才能運行,而這種執行的程序就稱之為進程,
Python 多進程開發與多線程開發
。程序和進程的區別就在于:程序是指令的集合,它是進程運行的靜態描述文本;進程是程序的一次執行活動,屬于動態概念。在多道編程中,我們允許多個程序同時加載到內存中,在操作系統的調度下,可以實現并發地執行。這是這樣的設計,大大提高了CPU的利用率。進程的出現讓每個用戶感覺到自己獨享CPU,因此,進程就是為了在CPU上實現多道編程而提出的。
有了進程為什么還要線程?
進程提供了多道編程,充分發揮了計算機部件的并行性,提高了計算機的利用率,既然進程這么優秀,為什么還要線程呢? 其實,還是有很多缺陷的,主要體現在兩點上:
進程只能在一個時間干一件事,如果想同時干兩件事或多件事,進程就無能為力了。
進程在執行的過程中如果阻塞,例如等待輸入,整個進程就會掛起,即使進程中有些工作不依賴于輸入的數據,也將無法執行。
而解決辦法就是讓單個進程,接受請求、等待I/O、處理計算并行起來,這樣很明顯可以避免同步等待,提高執行效率,在實際操作系統中這樣的機制就是——線程。
線程的優點
因為要并發,我們發明了進程,又進一步發明了線程。只不過進程和線程的并發層次不同:進程屬于在處理器這一層上提供的抽象;線程則屬于在進程這個層次上再提供了一層并發的抽象。如果我們進入計算機體系結構里,就會發現,流水線提供的也是一種并發,不過是指令級的并發。這樣,流水線、線程、進程就從低到高在三個層次上提供我們所迫切需要的并發!
除了提高進程的并發度,線程還有個好處,就是可以有效地利用多處理器和多核計算機。現在的處理器有個趨勢就是朝著多核方向發展,在沒有線程之前,多核并不能讓一個進程的執行速度提高,原因還是上面所有的兩點限制。但如果講一個進程分解為若干個線程,則可以讓不同的線程運行在不同的核上,從而提高了進程的執行速度。
例如:我們經常使用微軟的Word進行文字排版,實際上就打開了多個線程。這些線程一個負責顯示,一個接受鍵盤的輸入,一個進行存盤等等。這些線程一起運行,讓我們感覺到我們輸入和屏幕顯示同時發生,而不是輸入一些字符,過一段時間才能看到顯示出來。在我們不經意間,還進行了自動存盤操作。這就是線程給我們帶來的方便之處。
進程與線程的區別
進程是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。
線程是進程的一個實體, 是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位.線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
一個線程可以創建和撤銷另一個線程,同一個進程中的多個線程之間可以并發執行。
進程和線程的主要差別在于它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序 健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發操作,只能用線程,不能用進程。
Python 多進程(multiprocessing)
Unix/Linux操作系統提供了一個fork()系統調用,它非常特殊。普通的函數調用,調用一次,返回一次,但是fork()調用一次,返回兩次,因為操作系統自動把當前進程(稱為父進程)復制了一份(稱為子進程),然后,分別在父進程和子進程內返回,
電腦資料
《Python 多進程開發與多線程開發》(http://m.rusnota.com)。子進程永遠返回0,而父進程返回子進程的ID。這樣做的理由是,一個父進程可以fork出很多子進程,所以,父進程要記下每個子進程的ID,而子進程只需要調用getppid()就可以拿到父進程的ID。
Python的os模塊封裝了常見的系統調用,其中就包括fork,可以在Python程序中輕松創建子進程:
1
2
3
4
5
6
7
8
9
# multiprocessing.py
import os
print 'Process (%s) start...' % os.getpid()
pid = os.fork()
if pid==0:
print 'I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())
else:
print 'I (%s) just created a child process (%s).' % (os.getpid(), pid)
由于Windows沒有fork調用,上面的代碼在Windows上無法運行。
multiprocessing
multiprocessing是跨平臺版本的多進程模塊,它提供了一個Process類來代表一個進程對象,下面是示例代碼:
#!/usr/local/python27/bin/python2.7# coding=utf8# noinspection PyUnresolvedReferencesfrom multiprocessing import Processimport timedef f(n): time.sleep(1) print n*nfor i in range(10): p = Process(target=f,args=[i,]) p.start()
這個程序如果用單進程寫則需要執行10秒以上的時間,而用多進程則啟動10個進程并行執行,只需要用1秒多的時間。
在一般情況下多個進程的內存資源是相互獨立的,而多線程可以共享同一個進程中的內存資源,示例代碼:
#!/usr/local/python27/bin/python2.7# coding=utf8# noinspection PyUnresolvedReferences# 通過多進程和多線程對比,進程間內存無法共享,線程間的內存共享from multiprocessing import Processimport threadingimport timelock = threading.Lock()def run(info_list,n): lock.acquire() info_list.append(n) lock.release() print('%s\n' % info_list)info = []for i in range(10):'''target為子進程執行的函數,args為需要給函數傳遞的參數''' p = Process(target=run,args=[info,i]) p.start()'''這里是為了輸出整齊讓主進程的執行等一下子進程''' time.sleep(1) print('------------threading--------------')for i in range(10): p = threading.Thread(target=run,args=[info,i]) p.start()