最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python多進(jìn)程之進(jìn)程同步及通信詳解

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

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

進(jìn)程同步

當(dāng)多個(gè)進(jìn)程使用同一份數(shù)據(jù)資源的時(shí)候,因?yàn)檫M(jìn)程的運(yùn)行沒(méi)有順序,運(yùn)行起來(lái)也無(wú)法控制,如果不加以干預(yù),往往會(huì)引發(fā)數(shù)據(jù)安全或順序混亂的問(wèn)題,所以要在多個(gè)進(jìn)程讀寫(xiě)共享數(shù)據(jù)資源的時(shí)候加以適當(dāng)?shù)牟呗?,?lái)保證數(shù)據(jù)的一致性問(wèn)題。

Lock(鎖)

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

image.png

那么就可以使用Lock機(jī)制:

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機(jī)制,同一時(shí)間只能有一個(gè)進(jìn)程搶占到輸出資源,其他進(jìn)程等待該進(jìn)程結(jié)束,鎖釋放到,才可以搶占,這樣會(huì)解決多進(jìn)程間資源競(jìng)爭(zhēng)導(dǎo)致數(shù)據(jù)錯(cuò)亂的問(wèn)題,但是由并發(fā)執(zhí)行變成了串行執(zhí)行,會(huì)犧牲運(yùn)行效率。

進(jìn)程通信

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

Queue(隊(duì)列)

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

說(shuō)明

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

運(yùn)行結(jié)果為:

image.png

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

Pipe(管道)

Pipe常用于兩個(gè)進(jìn)程,兩個(gè)進(jìn)程分別位于管道的兩端,Pipe(duplex)方法返回(conn1,conn2)代表一個(gè)管道的兩端,duplex參數(shù)默認(rèn)為True,即全雙工模式,若為False,conn1只負(fù)責(zé)接收信息,conn2負(fù)責(zé)發(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__':
    # 主進(jìn)程創(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(信號(hào)量)

Semaphore用來(lái)控制對(duì)共享資源的訪問(wèn)數(shù)量,和進(jìn)程池的最大連接數(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個(gè)進(jìn)程同時(shí)執(zhí)行,那么來(lái)一個(gè)進(jìn)程獲得一把鎖,計(jì)數(shù)加1,當(dāng)計(jì)數(shù)等于2時(shí),后面再來(lái)的進(jìn)程均需要等待,等前面的進(jìn)程釋放掉,才可以獲得鎖。

信號(hào)量與進(jìn)程池的概念上類似,但是要區(qū)分開(kāi)來(lái),信號(hào)量涉及到加鎖的概念。

Event(事件)

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

Event常?函數(shù):

  • event.wait():在進(jìn)程中插入一個(gè)標(biāo)記(flag),默認(rèn)為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í)行")
    # 只會(huì)阻塞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("主進(jìn)程:flag設(shè)置為True")

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

image.png

總結(jié)

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

相關(guān)文章

  • python無(wú)法識(shí)別vim中文代碼的解決方案

    python無(wú)法識(shí)別vim中文代碼的解決方案

    這篇文章主要介紹了python無(wú)法識(shí)別vim中文代碼的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • python利用蒙版摳圖(使用PIL.Image和cv2)輸出透明背景圖

    python利用蒙版摳圖(使用PIL.Image和cv2)輸出透明背景圖

    這篇文章主要介紹了python利用蒙版摳圖(使用PIL.Image和cv2)輸出透明背景圖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Python爬蟲(chóng)網(wǎng)頁(yè)元素定位術(shù)

    Python爬蟲(chóng)網(wǎng)頁(yè)元素定位術(shù)

    這篇文章主要介紹了Python爬蟲(chóng)網(wǎng)頁(yè)元素定位術(shù),文章通過(guò)Beautiful?Soup模塊展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • 詳解Python的三種可變參數(shù)

    詳解Python的三種可變參數(shù)

    這篇文章主要介紹了Python的三種可變參數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Python基于sklearn庫(kù)的分類算法簡(jiǎn)單應(yīng)用示例

    Python基于sklearn庫(kù)的分類算法簡(jiǎn)單應(yīng)用示例

    這篇文章主要介紹了Python基于sklearn庫(kù)的分類算法,結(jié)合簡(jiǎn)單實(shí)例形式分析了Python使用sklearn庫(kù)封裝樸素貝葉斯、K近鄰、邏輯回歸、SVM向量機(jī)等常見(jiàn)機(jī)器學(xué)習(xí)算法的分類調(diào)用相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • Python批量解壓&壓縮文件夾的示例代碼

    Python批量解壓&壓縮文件夾的示例代碼

    這篇文章主要介紹了利用Python實(shí)現(xiàn)批量解壓&壓縮文件夾的示例代碼,文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的小伙伴快跟隨小編一起動(dòng)手試一試
    2022-04-04
  • 學(xué)習(xí)和使用python的13個(gè)理由

    學(xué)習(xí)和使用python的13個(gè)理由

    在本篇文章里小編給大家整理了關(guān)于學(xué)習(xí)和使用python的13個(gè)理由以及相關(guān)知識(shí)點(diǎn),需要的朋友們參考下。
    2019-07-07
  • python科學(xué)計(jì)算之numpy——ufunc函數(shù)用法

    python科學(xué)計(jì)算之numpy——ufunc函數(shù)用法

    今天小編就為大家分享一篇python科學(xué)計(jì)算之numpy——ufunc函數(shù)用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • Python文件的操作示例的詳細(xì)講解

    Python文件的操作示例的詳細(xì)講解

    本問(wèn)重點(diǎn)講解了Python文件的讀寫(xiě)原理、常用文件打開(kāi)模式、文件對(duì)象的常用方法和目錄的相關(guān)操作詳細(xì)講解,對(duì)Python文件操作相關(guān)知識(shí)感興趣的朋友跟隨小編一起看看吧
    2021-04-04
  • 使用OpenCV對(duì)運(yùn)動(dòng)員的姿勢(shì)進(jìn)行檢測(cè)功能實(shí)現(xiàn)

    使用OpenCV對(duì)運(yùn)動(dòng)員的姿勢(shì)進(jìn)行檢測(cè)功能實(shí)現(xiàn)

    2022年奧林匹克運(yùn)動(dòng)會(huì)如期舉行,以不正確的方式進(jìn)行運(yùn)動(dòng)風(fēng)險(xiǎn)在增加,人體姿勢(shì)估計(jì)是計(jì)算機(jī)視覺(jué)領(lǐng)域的重要問(wèn)題,接下來(lái)通過(guò)本文給大家介紹下使用OpenCV對(duì)運(yùn)動(dòng)員的姿勢(shì)進(jìn)行檢測(cè)功能,感興趣的朋友一起看看吧
    2022-02-02

最新評(píng)論

加查县| 凉城县| 武陟县| 石渠县| 纳雍县| 收藏| 合阳县| 申扎县| 宜都市| 共和县| 康乐县| 阳东县| 澳门| 金寨县| 双鸭山市| 昭平县| 浮山县| 黄梅县| 鞍山市| 格尔木市| 南投市| 丹东市| 富锦市| 新巴尔虎左旗| 阳山县| 仙桃市| 孟州市| 阿拉善右旗| 茌平县| 岱山县| 甘泉县| 米易县| 辽中县| 始兴县| 黔东| 张北县| 合川市| 建阳市| 洮南市| 山东| 佛山市|