首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果使用了lock,为什么aiohttp请求会阻塞?

如果使用了lock,为什么aiohttp请求会阻塞?
EN

Stack Overflow用户
提问于 2021-11-08 17:25:30
回答 1查看 39关注 0票数 0

为什么这段代码:

代码语言:javascript
运行
复制
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()])

打印:

代码语言:javascript
运行
复制
before acquiring 1
before request 1
before acquiring 2

然后又变得很糟糕?为什么标识符为%1的请求没有执行?与Thread (评论)相同,已尝试请求,正在工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-08 17:41:32

这是因为您将会阻塞整个执行线程的同步锁与要求所有操作都是非阻塞的asyncio混合在一起。您的两个协程(对test的两个调用)都在同一个线程中运行,因此当第二个协程试图获取锁,但被阻塞时,它也会阻止第一个协程(持有锁)进行任何额外的处理。

您可以通过使用asyncio.Lock来修复此问题。它只会阻塞等待锁的协程,而不是阻塞整个线程。注意,这个锁不能在进程之间传递,所以除非您停止使用multiprocessing,否则它不会工作,这在上面的示例代码中实际上并不是必需的。您只需创建一个仅在单个子进程中使用的锁,因此您可以在子进程中创建asyncio.Lock,而不会丢失任何功能。

但是,如果您的实际用例需要一个也可以在进程之间共享的asyncio-friendly锁,那么您可以使用aioprocessing来实现这一点(完全公开:我是aioprocessing的作者)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69887532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档