前面的文章介紹瞭如何進行進程間的通訊方式。結下來咱們來說一講如何管理多個進程對資源的訪問。
例若有時候咱們多個進程對某一個文件進行寫入的時候,若是咱們一個進程尚未寫完,就被CPU切換到另外一個進程,勢必會形成文件寫入的順序亂七八糟的。正確的狀況是,在一個進程寫完的時候,再讓另外一個進程進行寫入。這時候,咱們須要一個鎖。windows
Lock有一點像咱們平常生活中上廁所。廁所就是咱們的資源,能夠解決咱們的需求。可是廁所是有限的,並且一次只能進去一我的。同時想上廁所的人不少,還沒輪到的人所有在外邊等待,輪到的人能夠進去使用廁所,同時會鎖上門,禁止其餘人進入。上完廁所的人出來,打開廁所門,讓後面的人進來。
翻譯成計算機語言就是:
這個資源只容許一個Process訪問,所以只有一個門,上一把鎖。
app
from multiprocessing import Lock, Pool import random def write_file(lock): with lock: with open('write_demo.txt', 'a') as wf: wf.write(str(random.random())+"\r") if __name__ == '__main__': lock = Lock() pool = Pool() for i in range(0, 10): pool.apply_async(write_file(lock)) pool.close()
注意: lock其實跟文件的打開關閉同樣,可使用with語句。dom
Lock supports the context manager protocol and thus may be used in with statements.
解釋一下這裏爲何是with lock
:由於在if __name__ == '__main__':
中咱們已經建立了Lock
對象。而with
後是須要跟一個對象,所以直接將lock
寫在後面便可。那麼with後的代碼塊都是被with所保護。
若是不用with語句的話,則須要手動寫:async
lock.acquire() lock.release()
二者之間的代碼纔是被鎖保護的。ui
RLock是Lock的遞歸版。啥意思呢?
咱們知道lock.aquire()
是請求鎖,噹噹前的鎖事鎖定狀態的時候,則lock.aquire()
則會阻塞等待鎖釋放。
所以若是咱們寫了兩個lock.aquire()
則會產生死鎖。第二個lock.aquire()
會永遠等待在那裏。spa
使用RLock則不會有這種狀況。RLock一個門支持多個鎖,上多少把鎖,就得釋放多少次。
翻譯
Semaphore有信號燈的意思。
Semaphore跟Lock相似,可是Semaphore能夠容許指定最多多少個進程訪問資源。
就像該資源有多個門,每一個門一把鎖。一個進程訪問了資源,鎖了門,還有其餘門可使用。可是若是全部門都被使用了,那麼就得等待有進程出來釋放鎖才能夠。
在編寫Sempaphore示例代碼的時候,遇到了一個比較奇怪的問題。unix
from multiprocessing import Semaphore, Pool import os import time def worker_process(s): print id(s) with s: print "Process (%s) run" % os.getpid() time.sleep(1) print "Process (%s) ended" % os.getpid() if __name__ == '__main__': semaphore = Semaphore(1) print id(semaphore) pool = Pool(4) for i in range(0, 1000): pool.apply_async(worker_process, args=(semaphore,)) pool.close() pool.join() print "Main Process ended"
如上所示的代碼,傳遞semaphore時候,worker_process
並不會執行。
可是若是將semaphore
定義成一個全局變量,那麼則能夠在Linux或者unix下執行。(懷疑會在windows下出錯)code
from multiprocessing import Semaphore, Pool import os import time semaphore = Semaphore(1) def worker_process(): print id(semaphore) with semaphore: print "Process (%s) run" % os.getpid() time.sleep(1) print "Process (%s) ended" % os.getpid() if __name__ == '__main__': print id(semaphore) pool = Pool(4) for i in range(0, 1000): pool.apply_async(worker_process) pool.close() pool.join() print "Main Process ended"
以上代碼能夠正確執行。
暫時不知道問題出在哪裏?有會的網友還請指點。對象
還有Event。Event也是用於進程間的通訊,那麼它跟Queue、Pipe有什麼區別呢?
其實Python多進程還有許多的內容。在後續的文章中介紹。