雖然可以用文件共享數(shù)據(jù)實現(xiàn)進程間通信,但問題是:
1)效率低(共享數(shù)據(jù)基于文件,而文件是硬盤上的數(shù)據(jù))2)需要自己加鎖處理
因此我們最好找尋一種解決方案能夠兼顧:1)效率高(多個進程共享一塊內(nèi)存的數(shù)據(jù))2)幫我們處理好鎖問題。
mutiprocessing模塊為我們提供的基于消息的IPC通信機制:隊列和管道。
1隊列和管道都是將數(shù)據(jù)存放于內(nèi)存中
2隊列又是基于(管道+鎖)實現(xiàn)的,可以讓我們從復(fù)雜的鎖問題中解脫出來,我們應(yīng)該盡量避免使用共享數(shù)據(jù),盡可能使用消息傳遞和隊列,避免處理復(fù)雜的同步和鎖問題,而且在進程數(shù)目增多時,往往可以獲得更好的可獲展性
1.隊列(推薦使用)
創(chuàng)建隊列的類(底層就是以管道和鎖定的方式實現(xiàn)):
Queue([maxsize]):創(chuàng)建共享的進程隊列,Queue是多進程安全的隊列,可以使用Queue實現(xiàn)多進程之間的數(shù)據(jù)傳遞。
參數(shù)介紹:
maxsize是隊列中允許最大項數(shù),省略則無大小限制。
應(yīng)用:
隊列的使用
什么是生產(chǎn)者消費者模式
生產(chǎn)者消費者模式是通過一個容器來解決生產(chǎn)者和消費者的強耦合問題。生產(chǎn)者和消費者彼此之間不直接通訊,而通過阻塞隊列來進行通訊,所以生產(chǎn)者生產(chǎn)完數(shù)據(jù)之后不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產(chǎn)者要數(shù)據(jù),而是直接從阻塞隊列里取,阻塞隊列就相當于一個緩沖區(qū),平衡了生產(chǎn)者和消費者的處理能力。
基于隊列的生產(chǎn)者消費者模型
此時的問題是主進程永遠不會結(jié)束,原因是:生產(chǎn)者p在生產(chǎn)完后就結(jié)束了,但是消費者c在取空了q之后,則一直處于死循環(huán)中且卡在q.get()這一步。
解決方式無非是讓生產(chǎn)者在生產(chǎn)完畢后,往隊列中再發(fā)一個結(jié)束信號,這樣消費者在接收到結(jié)束信號后就可以break出死循環(huán)。
生產(chǎn)者在生產(chǎn)完畢后發(fā)送結(jié)束信號None
注意:結(jié)束信號None,不一定要由生產(chǎn)者發(fā),主進程里同樣可以發(fā),但主進程需要等生產(chǎn)者結(jié)束后才應(yīng)該發(fā)送該信號
主進程在生產(chǎn)者生產(chǎn)完畢后發(fā)送結(jié)束信號None
但上述解決方式,在有多個生產(chǎn)者和多個消費者時,應(yīng)該怎么做呢?有幾個消費者就發(fā)幾次信號?
有幾個消費者就應(yīng)該發(fā)送幾次結(jié)束信號None
其實我們的思路無非是發(fā)送結(jié)束信號而已,有另外一種隊列提供了這種機制
#JoinableQueue([maxsize]):這就像是一個Queue對象,但隊列允許項目的使用者通知生成者項目已經(jīng)被成功處理。通知進程是使用共享的信號和條件變量來實現(xiàn)的。
#參數(shù)介紹:
maxsize是隊列中允許最大項數(shù),省略則無大小限制。
#方法介紹:
JoinableQueue的實例p除了與Queue對象相同的方法之外還具有:
q.task_done():使用者使用此方法發(fā)出信號,表示q.get()的返回項目已經(jīng)被處理。如果調(diào)用此方法的次數(shù)大于從隊列中刪除項目的數(shù)量,將引發(fā)ValueError異常
q.join():生產(chǎn)者調(diào)用此方法進行阻塞,直到隊列中所有的項目均被處理。阻塞將持續(xù)到隊列中的每個項目均調(diào)用q.task_done()方法為止
以上內(nèi)容為大家介紹了python進程間通信,希望對大家有所幫助,如果想要了解更多Python相關(guān)知識,請關(guān)注IT培訓(xùn)機構(gòu):千鋒教育。