為什么這段代碼:
import asyncio
import time
from multiprocessing import Pool, Manager
from threading import Thread, Lock
from aiohttp import ClientSession
async def test(s: ClientSession, lock: Lock, identifier):
print(f'before acquiring {identifier}')
lock.acquire()
print(f'before request {identifier}')
async with s.get('http://icanhazip.com') as r:
print(f'after request {identifier}')
lock.release()
print(f'after releasing {identifier}')
async def main(lock: Lock):
async with ClientSession() as s:
await asyncio.gather(test(s, lock, 1), test(s, lock, 2))
def run(lock: Lock):
asyncio.run(main(lock))
if __name__ == '__main__':
# Thread(target=run, args=[Lock()]).start()
with Pool(processes=1) as pool:
pool.map(run, [Manager().Lock()])
印刷:
before acquiring 1
before request 1
before acquiring 2
然后卡住了?為什么沒有執行識別符號為 1 的請求?與 Thread 相同(評論)嘗試請求,作業。
uj5u.com熱心網友回復:
發生這種情況是因為您正在混合同步鎖,它會阻塞整個執行執行緒asyncio,而 需要所有操作都是非阻塞的。您的兩個協程(對 的兩次呼叫test)都在同一執行緒中運行,因此當第二個協程嘗試獲取鎖但被阻塞時,它也會阻止第一個協程(持有鎖)進行任何額外的處理。
您可以使用 aasyncio.Lock來解決此問題。它只會阻塞等待鎖的協程,而不是阻塞整個執行緒。請注意,此鎖不能在行程之間傳遞,因此除非您停止使用multiprocessing,否則它不會起作用,這在上面的示例代碼中實際上不是必需的。您只需創建一個僅在單個子行程中使用的鎖,因此您可以簡單地asyncio.Lock在子行程中創建 ,而不會丟失任何功能。
但是,如果您的實際用例需要一個asyncio友好的鎖,該鎖也可以在您可以使用的行程之間共享aioprocessing(完全披露:我是 的作者aioprocessing)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/353550.html
上一篇:比較csv檔案中的兩列
