python_多進程_multiprocessing

1、進程的概念

什麼是進程—>CPU在同一時刻只能處理一個任務,只是因爲cpu執行速度很快。 
cpu在各個任務之間來回的進行切換。 
進程的概念:正在進行的一個過程或者說一個任務,而負責執行任務的則是CPU,進程本身是 一個抽象的概念,即進程就是一個過程、一個任務。 
CPU描述的是一個程序的執行過程. 
進程之間是如何做到併發的:CPU在各個任務之間來回的進行切換,並在切換的過程當中保存當前進程的執行狀態(保存蛋糕的執行過程)。 
進程與程序的區別:程序相當於菜譜,而進程相當於做菜的整個過程。 
需要強調的是:同一個程序執行兩次(雙擊),那也是兩個進程,比如打開暴風影音,雖然都是同一個軟件,但是一個可以播放a,一個可以播放b. 
核的概念:https://zhidao.baidu.com/question/541410131.html 
處理器,就是說有幾個處理器。。。也就說一個CPU裏面會有幾個處理器,這樣就可以同時處理幾個要求了。。。

2、並行與併發的區別

無論是並行還是併發,在用戶看來都是同時運行的,不管是進程還是線程,都只是一個任務而已, 真正幹活的是CPU,CPU來做這些任務,而一個cpu(單核)同一時刻只能執行一個任務。 
並行:多個任務同時運行,只有具備多個cpu才能實現並行,含有幾個cpu,也就意味着在同一時刻可以執行幾個任務。 
併發:是僞並行,即看起來是同時運行的,實際上是單個CPU在多道程序之間來回的進行切換。

3、同步與異步的概念

同步就是指一個進程在執行某個請求的時候,若該請求需要一段時間才能返回信息,那麼這個進程將會一直等待下去,直到收到返回信息才繼續執行下去。 
異步是指進程不需要一直等下去,而是繼續執行下面的操作,不管其他進程的狀態。當有消息返回時系統會通知進行處理,這樣可以提高執行的效率。 
打電話的過程就是同步通信,發短信時就是異步通信。

4、進程創建的方式

用戶創建出來的所有進程都是由操作系統負責的,因此無論是哪一種創建進程的方式,實際上都是調用操作系統的接口創建的,進程的切換都是由操作系統控制的。 
無論哪一種創建進程的方式,新進程的創建都是由一個已經存在的進程執行了一個用於創建進程的系統調用而創建的。

5、父進程和子進程之間的關係

子進程創建後,父進程和子進程有各自不同的地址空間,多道技術要求物理層面實現進程之間內存的隔離,任何一個進程在其地址空間的修改都不會影響到另外一個進程。 
注意:子進程和父進程之間是可以有隻讀的共享的內存區域的。 
進程與進程之間數據(資源)是隔離的,兩個進程之間可以基於管道這種方式進行通信。在Unix當中,是含有進程層次的概念的,但是在windows當中,是沒有進程層次的概念的,所有的進程都是地位相同的。 
在Linux當中,每啓動一個命令,都會啓動一個進程。

6、線程的相關概念

1 線程的概念 
一個進程裏面至少有一個控制線程,進程的概念只是一種抽象的概念,真正在CPU上面調度的是進程裏面的線程,就好比真正在地鐵這個進程裏面工作的實際上是地鐵裏面的線程,北京地鐵裏面至少要有一個線程,線程是真正幹活的,線程用的是進程裏面包含的一堆資源,線程僅僅是一個調度單位,不包含資源。

3 什麼時候需要開啓多個線程? 
什麼時候需要開啓多個線程:一個進程裏面的多個線程共享這個進程裏面的資源,因此如果多個任務共享同一塊資源的時候,需要開啓多個線程。 
多線程指的是,在一個進程中開啓多個線程,簡單的說:如果多個任務共用同一個資源空間,那麼必須在一個進程內開啓多個線程。

4 一個進程裏面需要包含多個線程? 
一個進程這個任務裏面可能對應多個分任務,如果一個進程裏面只開啓一個線程的話,多個分任務之間實際上是串行的執行效果,即一個程序裏面只含有一條執行路徑。

5 多線程和多進程的關係 
對於計算密集型應用,應該使用多進程;對於IO密集型應用,應該使用多線程。 
線程的創建比進程的創建開銷小的多。

6 Python中線程的特點 
在其他語言當中,一個進程裏面開啓多個線程,每個線程都可以給一個cpu去使用,但是在python當中,在同一時刻,一個進程當中只能有一個線程處於運行狀態。 
eg:在其他語言當中,比如我現在開啓了一個進程,這個進程當中含有幾個線程,如果我現在有多個cpu,每一個線程是可以對應相應的CPU的。 
但是在python當中,如果我們現在開啓了一個進程,這個進程裏面對應多個線程,同一時刻只有一個線程可以處於運行狀態。 
對於其他語言而言,在多CPU系統中,爲了最大限度的利用多核,可以開啓多個線程。 
但是Python中的多線程是利用不了多核優勢的。

進程與線程的區別: 
在同一個進程當中,多個線程彼此之間可以相互通信;但是進程與進程之間的通信必須基於IPC這種消息的通信機制(IPC機制包括隊列和管道)。 
在一個進程當中,改變主線程可能會影響其它線程的行爲,但是改變父進程並不會影響其它子進程的行爲,因爲進程與進程之間是完全隔離的。 
在python當中,在同一時刻同一進程當中只能同時有一個線程在運行,如果有一個線程使用了系統調用而阻塞,那麼整個進程都會被掛起。

================================================================================================以上內容爲轉載

================================================================================================

以下內容爲原創

1.鎖

 

鎖是爲了確保數據一致性,比如讀寫鎖,每個進程給一個變量增加 1 ,但是如果在一個進程讀取但還沒有寫入的時候,另外的進程也同時讀取了,並寫入該值,則最後寫入的值是錯誤的,這時候就需要鎖。

測試數據(1,2,3,4,5,6,7,8,9,10)存在data文件中

不加鎖

import os
from multiprocessing import  Process,Lock
import time
import random
 
def work():  # 買票
        data=[]
 
        with open('/home/user/6-StudyExcise/studyPython/data') as file:
            for line in file.readlines():
                data.append(line.replace('\n',''))
        print('剩餘票數: %s' % len(data))
        if len(data)>0:
            data=data[0:len(data)-1]
            time.sleep(random.randint(110))  # 模擬網絡延遲
            print(data)
            with open('/home/user/6-StudyExcise/studyPython/data','w',encoding='utf-8') as file:
                for in data:
                    file.write(i+'_10'+'\n')
            print('%s 購票成功' % os.getpid())
        else:
            print('%s 購票失敗' % os.getpid())
if __name__=='__main__':
    # lock = Lock()
    p_l = []
    for in range(5):
        = Process(target=work)
        p_l.append(p)
        p.start()
    for in p_l:
        p.join()
 
    with open('/home/user/6-StudyExcise/studyPython/data') as file:
        str=file.read()
        print(str)

加鎖

import os
from multiprocessing import  Process,Lock
import time
import random
 
def work(lock):  # 買票
    data=[]
    with lock:
        with open('/home/user/6-StudyExcise/studyPython/data') as file:
            for line in file.readlines():
                data.append(line.replace('\n',''))
        print('剩餘票數: %s' % len(data))
        if len(data)>0:
            data=data[0:len(data)-1]
            time.sleep(random.randint(110))  # 模擬網絡延遲
            print(data)
            with open('/home/user/6-StudyExcise/studyPython/data','w',encoding='utf-8') as file:
                for in data:
                    file.write(i+'_10'+'\n')
            print('%s 購票成功' % os.getpid())
        else:
            print('%s 購票失敗' % os.getpid())
if __name__=='__main__':
    lock = Lock()
    p_l = []
    for in range(5):
        = Process(target=work,args=(lock,))
        p_l.append(p)
        p.start()
    for in p_l:
        p.join()
 
    with open('/home/user/6-StudyExcise/studyPython/data') as file:
        str=file.read()
        print(str

 

說明:

當多進程共享一個文件時,不加鎖會導致對文件修改與實際不一致(混亂)(左圖),加鎖後,每個進程依次得到文件讀寫權限(右圖)

2.join:阻塞的是主進程,比如:xx.join(),那麼主進程只會在xx執行完之後才執行

#encoding:utf-8
from multiprocessing import Process
import os, time, random
 
def r1(process_name):
    for in range(5):
        print (process_name, os.getpid())     #打印出當前進程的id
        time.sleep(random.random())
def r2(process_name):
    for in range(5):
        print (process_name, os.getpid() )    #打印出當前進程的id
        time.sleep(random.random()*2)
 
if __name__ == "__main__":
        print ("main process run...")
        p1 = Process(target=r1, args=('process_name1', ))
        p2 = Process(target=r2, args=('process_name2', ))
        p1.start()
        p2.start()
        p1.join()
        p2.join()
        print ("main process runned all lines...")

 

說明:

1.執行p1.join(), p2.join(),之後,,,主線程的 print ("main process runned all lines...")纔會執行,(左圖)

2.p1.join(),但是p2沒有執行join ,,主線程的 print ("main process runned all lines...") 在等p1執行完之後纔會執行,(右圖)

3.如果代碼順序如下:

p1.start()

p1.join()

p2.start()

則會在執行完p1,會執行主線程的 print ("main process runned all lines..."),最後纔會執行p2,因爲join是用來阻塞當前線程的,p1.start()之後,p1就提示主線程,需要等待p1結束才向下執行,那主線程就乖乖的等着啦,自然沒有執行p2.start()這一句啦,當然就變成了圖示的效果了。

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