欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python多進程之進程同步及通信詳解

 更新時間:2021年11月25日 15:48:19   作者:程序員-夏天  
這篇文章主要為大家介紹了Python多進程之進程同步及通信,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

上篇文章介紹了什么是進程、進程與程序的關(guān)系、進程的創(chuàng)建與使用、創(chuàng)建進程池等,接下來就來介紹一下進程同步及進程通信。

進程同步

當多個進程使用同一份數(shù)據(jù)資源的時候,因為進程的運行沒有順序,運行起來也無法控制,如果不加以干預(yù),往往會引發(fā)數(shù)據(jù)安全或順序混亂的問題,所以要在多個進程讀寫共享數(shù)據(jù)資源的時候加以適當?shù)牟呗?,來保證數(shù)據(jù)的一致性問題。

Lock(鎖)

一個Lock對象有兩個方法:acquire()和release()來控制共享數(shù)據(jù)的讀寫權(quán)限, 看下面這張圖片,使用多進程的時候會經(jīng)常出現(xiàn)這種情況,這是因為多個進程都在搶占輸出資源,共享同一打印終端,從而造成了輸出信息的錯亂。

image.png

那么就可以使用Lock機制:

import multiprocessing
import random
import time
def work(lock, i):
    lock.acquire()
    print("work'{}'執(zhí)行中......".format(i), multiprocessing.current_process().name, multiprocessing.current_process().pid)
    time.sleep(random.randint(0, 2))
    print("work'{}'執(zhí)行完畢......".format(i))
    lock.release()
if __name__ == '__main__':
    lock = multiprocessing.Lock()
    for i in range(5):
        p = multiprocessing.Process(target=work, args=(lock, i))
        p.start()

由于引入了Lock機制,同一時間只能有一個進程搶占到輸出資源,其他進程等待該進程結(jié)束,鎖釋放到,才可以搶占,這樣會解決多進程間資源競爭導致數(shù)據(jù)錯亂的問題,但是由并發(fā)執(zhí)行變成了串行執(zhí)行,會犧牲運行效率。

進程通信

上篇文章說過,進程之間互相隔離,數(shù)據(jù)是獨立的,默認情況下互不影響,那要如何實現(xiàn)進程間通信呢?Python提供了多種進程通信的方式,下面就來說一下。

Queue(隊列)

multiprocessing模塊提供的Queue多進程安全的消息隊列,可以實現(xiàn)多進程之間的數(shù)據(jù)傳遞。

說明

  • 初始化Queue()對象時(例如:q=Queue()),若括號中沒有指定最?可接收的消息數(shù)量,或數(shù)量為負值,那么就代表可接受的消息數(shù)量沒有上限(直到內(nèi)存的盡頭)。
  • Queue.qsize():返回當前隊列包含的消息數(shù)量。
  • Queue.empty():如果隊列為空,返回True,反之False。
  • Queue.full():如果隊列滿了,返回True,反之False。
  • Queue.get(block, timeout):獲取隊列中的?條消息,然后將其從列隊中移除,block默認值為True。如果block使?默認值,且沒有設(shè)置timeout(單位秒),消息列隊如果為空,此時程序?qū)⒈蛔枞ㄍT谧x取狀態(tài)),直到從消息列隊讀到消息為?,如果設(shè)置了timeout,則會等待timeout秒,若還沒讀取到任何消息,則拋出Queue.Empty異常;如果block值為False,消息列隊如果為空,則會?刻拋出Queue.Empty異常。
  • Queue.get_nowait():相當Queue.get(False)。
  • Queue.put(item, block, timeout):將item消息寫?隊列,block默認值為True,如果block使?默認值,且沒有設(shè)置timeout(單位秒),消息列隊如果已經(jīng)沒有空間可寫?,此時程序?qū)⒈蛔枞ㄍT趯?狀態(tài)),直到消息列隊騰出空間為?,如果設(shè)置了timeout,則會等待timeout秒,若還沒空間,則拋出Queue.Full異常;如果block值為False,消息列隊如果沒有空間可寫?,則會?刻拋出Queue.Full異常。
  • Queue.put_nowait(item):相當于Queue.put(item, False)。
from multiprocessing import Process, Queue
import time
def write_task(queue):
    """
    向隊列中寫入數(shù)據(jù)
    :param queue: 隊列
    :return:
    """
    for i in range(5):
        if queue.full():
            print("隊列已滿!")
        message = "消息{}".format(str(i))
        queue.put(message)
        print("消息{}寫入隊列".format(str(i)))
def read_task(queue):
    """
    從隊列讀取數(shù)據(jù)
    :param queue: 隊列
    :return:
    """
    while True:
        print("從隊列讀取:{}".format(queue.get(True)))
if __name__ == '__main__':
    print("主進程執(zhí)行......")
    # 主進程創(chuàng)建Queue,最大消息數(shù)量為3
    queue = Queue(3)
    pw = Process(target=write_task, args=(queue, ))
    pr = Process(target=read_task, args=(queue, ))
    pw.start()
    pr.start()

運行結(jié)果為:

image.png

從結(jié)果我們可以看出,隊列最大可以放入3條消息,后面再來消息,要等read_task從隊列里取出后才行。

Pipe(管道)

Pipe常用于兩個進程,兩個進程分別位于管道的兩端,Pipe(duplex)方法返回(conn1,conn2)代表一個管道的兩端,duplex參數(shù)默認為True,即全雙工模式,若為False,conn1只負責接收信息,conn2負責發(fā)送。

send()和recv()方法分別是發(fā)送和接受消息的方法。

import multiprocessing
import time
import random
def proc_send(pipe):
    """
    發(fā)送消息
    :param pipe:管道一端
    :return:
    """
    for i in range(10):
        print("process send:{}".format(str(i)))
        pipe.send(i)
        time.sleep(random.random())
def proc_recv(pipe):
    """
    接收消息
    :param pipe:管道一端
    :return:
    """
    while True:
        print("Process recv:{}".format(pipe.recv()))
        time.sleep(random.random())
if __name__ == '__main__':
    # 主進程創(chuàng)建pipe
    pipe = multiprocessing.Pipe()
    p1 = multiprocessing.Process(target=proc_send,args=(pipe[0], ))
    p2 = multiprocessing.Process(target=proc_recv,args=(pipe[1], ))
    p1.start()
    p2.start()
    p1.join()
    p2.terminate()

執(zhí)行結(jié)果為:

image.png

Semaphore(信號量)

Semaphore用來控制對共享資源的訪問數(shù)量,和進程池的最大連接數(shù)類似。

import multiprocessing
import random
import time
def work(s, i):
    s.acquire()
    print("work'{}'執(zhí)行中......".format(i), multiprocessing.current_process().name, multiprocessing.current_process().pid)
    time.sleep(i*2)
    print("work'{}'執(zhí)行完畢......".format(i))
    s.release()
if __name__ == '__main__':
    s = multiprocessing.Semaphore(2)
    for i in range(1, 7):
        p = multiprocessing.Process(target=work, args=(s, i))
        p.start()

上面的代碼中使用Semaphore限制了最多有2個進程同時執(zhí)行,那么來一個進程獲得一把鎖,計數(shù)加1,當計數(shù)等于2時,后面再來的進程均需要等待,等前面的進程釋放掉,才可以獲得鎖。

信號量與進程池的概念上類似,但是要區(qū)分開來,信號量涉及到加鎖的概念。

Event(事件)

Event用來實現(xiàn)進程間同步通信的。運行的機制是:全局定義了一個flag,如果flag值為False,當程序執(zhí)行event.wait()方法時就會阻塞,如果flag值為True時,程序執(zhí)行event.wait()方法時不會阻塞繼續(xù)執(zhí)行。

Event常?函數(shù):

  • event.wait():在進程中插入一個標記(flag),默認為False,可以設(shè)置timeout。
  • event.set():使flag為Ture。
  • event.clear():使flag為False。
  • event.is_set():判斷flag是否為True。
import multiprocessing
import time
def wait_for_event(e):
    print("wait_for_event執(zhí)行")
    e.wait()
    print("wait_for_event: e.is_set():{}".format(e.is_set()))
def wait_for_event_timeout(e, t):
    print("wait_for_event_timeout執(zhí)行")
    # 只會阻塞2s
    e.wait(t)
    print("wait_for_event_timeout:e.is_set:{}".format(e.is_set()))
if __name__ == "__main__":
    e = multiprocessing.Event()
    p1 = multiprocessing.Process(target=wait_for_event, args=(e,))
    p1.start()
    p2 = multiprocessing.Process(target=wait_for_event_timeout, args=(e, 2))
    p2.start()
    time.sleep(4)
    # 4s之后使用e.set()將flag設(shè)為Ture
    e.set()
    print("主進程:flag設(shè)置為True")

執(zhí)行結(jié)果如下:

image.png

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Python寫捕魚達人的游戲?qū)崿F(xiàn)

    Python寫捕魚達人的游戲?qū)崿F(xiàn)

    這篇文章主要介紹了Python寫捕魚達人的游戲?qū)崿F(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • 基于Python制作一個端午節(jié)相關(guān)的小游戲

    基于Python制作一個端午節(jié)相關(guān)的小游戲

    端午節(jié)快樂,今天我將為大家?guī)硪黄嘘P(guān)端午節(jié)的編程文章,希望能夠為大家獻上一份小小的驚喜,我們將會使用Python來實現(xiàn)一個與端午粽子相關(guān)的小應(yīng)用程序,在本文中,我將會介紹如何用Python代碼制做一個“粽子拆解器”,感興趣的小伙伴歡迎閱讀
    2023-06-06
  • 解決linux下使用python打開terminal時報錯的問題

    解決linux下使用python打開terminal時報錯的問題

    這篇文章主要介紹了linux下使用python打開terminal時報錯,本文通過兩種場景分析給大家詳細講解,需要的朋友可以參考下
    2023-03-03
  • python 獲取utc時間轉(zhuǎn)化為本地時間的方法

    python 獲取utc時間轉(zhuǎn)化為本地時間的方法

    今天小編就為大家分享一篇python 獲取utc時間轉(zhuǎn)化為本地時間的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • Python爬蟲實現(xiàn)模擬點擊動態(tài)頁面

    Python爬蟲實現(xiàn)模擬點擊動態(tài)頁面

    這篇文章主要介紹了Python爬蟲實現(xiàn)模擬點擊動態(tài)頁面,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • Python3 文章標題關(guān)鍵字提取的例子

    Python3 文章標題關(guān)鍵字提取的例子

    今天小編就為大家分享一篇Python3 文章標題關(guān)鍵字提取的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • 解決windows下Sublime Text 2 運行 PyQt 不顯示的方法分享

    解決windows下Sublime Text 2 運行 PyQt 不顯示的方法分享

    問題描述:PyQt 環(huán)境正常,可以使用 Windows 的 虛擬 DOS 正常運行,但在 Sublime Text 2 下使用 Ctrl + B 運行后,界面不顯示,但查看任務(wù)管理器,有 python.exe 進程。
    2014-06-06
  • Python圖像特效之模糊玻璃效果

    Python圖像特效之模糊玻璃效果

    這篇文章主要為大家詳細介紹了Python圖像特效之模糊玻璃效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Scrapy框架爬取Boss直聘網(wǎng)Python職位信息的源碼

    Scrapy框架爬取Boss直聘網(wǎng)Python職位信息的源碼

    今天小編就為大家分享一篇關(guān)于Scrapy框架爬取Boss直聘網(wǎng)Python職位信息的源碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Python Numpy庫常見用法入門教程

    Python Numpy庫常見用法入門教程

    這篇文章主要介紹了Python Numpy庫常見用法,結(jié)合實例形式詳細Fenix了Python numpy庫基本功能、原理以及數(shù)組常見操作技巧,需要的朋友可以參考下
    2020-01-01

最新評論