簡體   English   中英

如何將 asyncio 與其他操作系統線程同步?

[英]How can I synchronize asyncio with other OS threads?

我有一個帶有一個主線程的程序,我在其中生成了第二個使用 asyncio 的線程。 是否提供了任何工具來同步這兩個線程? 如果一切都是異步的,我可以用它的同步原語來做,例如:

import asyncio

async def taskA(lst, evt):
    print(f'Appending 1')
    lst.append(1)
    evt.set()

async def taskB(lst, evt):
    await evt.wait()
    print('Retrieved:', lst.pop())

lst = []
evt = asyncio.Event()
asyncio.get_event_loop().run_until_complete(asyncio.gather(
    taskA(lst, evt),
    taskB(lst, evt),
))

但是,這不適用於多線程。 如果我只使用一個threading.Event那么它會阻塞 asyncio 線程。 我想我可以將等待推遲到執行者:

import asyncio
import threading

def taskA(lst, evt):
    print(f'Appending 1')
    lst.append(1)
    evt.set()

async def taskB(lst, evt):
    asyncio.get_event_loop().run_in_executor(None, evt.wait)
    print('Retrieved:', lst.pop())

def targetA(lst, evt):
    taskA(lst, evt)

def targetB(lst, evt):
    asyncio.set_event_loop(asyncio.new_event_loop())
    asyncio.get_event_loop().run_until_complete(taskB(lst, evt))

lst = []
evt = threading.Event()
threadA = threading.Thread(target=targetA, args=(lst, evt))
threadB = threading.Thread(target=targetB, args=(lst, evt))
threadA.start()
threadB.start()
threadA.join()
threadB.join()

但是,讓執行程序線程只等待互斥鎖似乎不自然。 這是應該這樣做的方式嗎? 或者有沒有其他方法可以異步等待操作系統線程之間的同步?

將 asyncio 協程與來自另一個線程的事件同步的一種簡單方法是在 taskB 中等待asyncio.Event ,並使用loop.call_soon_threadsafe從 taskA 設置它。

為了能夠在兩者之間傳遞值和異常,您可以使用期貨; 但是,您正在發明很多run_in_executor 如果 taskA 的唯一工作是從隊列中取出任務,您不妨創建一個單工“池”並將其用作您的工作線程。 然后您可以按預期使用run_in_executor

worker = concurrent.futures.ThreadPoolExecutor(max_workers=1)

async def taskB(lst):
    loop = asyncio.get_event_loop()
    # or result = await ..., if taskA has a useful return value
    # This will also propagate exceptions raised by taskA
    await loop.run_in_executor(worker, taskA, lst)
    print('Retrieved:', lst.pop())

語義與具有顯式隊列的版本相同 - 隊列仍然存在,它只是在ThreadPoolExecutor內部。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM