什么';的Python asyncio.Lock()?

什么';的Python asyncio.Lock()?,python,python-asyncio,Python,Python Asyncio,是因为协同程序在未来可能会被抢占吗?或者,它允许人们在关键部分(我不应该鼓励这样做)中使用收益率?您使用它的原因与使用线程代码锁定的原因相同:保护关键部分asyncio主要用于单线程代码,但仍然会发生并发执行(只要您从或等待中获得收益),这意味着您有时需要同步 例如,考虑从Web服务器获取一些数据的函数,然后缓存结果: async def get_stuff(url): if url in cache: return cache[url] stuff = awai

是因为协同程序在未来可能会被抢占吗?或者,它允许人们在关键部分(我不应该鼓励这样做)中使用收益率?

您使用它的原因与使用线程代码锁定的原因相同:保护关键部分
asyncio
主要用于单线程代码,但仍然会发生并发执行(只要您从或等待中获得
收益),这意味着您有时需要同步

例如,考虑从Web服务器获取一些数据的函数,然后缓存结果:

async def get_stuff(url):
    if url in cache:
        return cache[url]
    stuff = await aiohttp.request('GET', url)
    cache[url] = stuff
    return stuff
现在假设您有多个并发运行的co例程,可能需要使用
get\u stuff
的返回值:

async def parse_stuff():
    stuff = await get_stuff()
    # do some parsing

async def use_stuff():
    stuff = await get_stuff()
    # use stuff to do something interesting

async def do_work():
     out = await aiohttp.request("www.awebsite.com")
     # do some work with out


loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
    parse_stuff(),
    use_stuff(),
    do_work(),
))
现在,假设从
url
获取数据很慢。如果
parse_stuff
use_stuff
同时运行,则每个人都将承担通过网络获取
stuff
的全部成本。如果使用锁保护方法,则可以避免以下情况:

stuff_lock = asyncio.Lock()

async def get_stuff(url):
    async with stuff_lock:
        if url in cache:
            return cache[url]
        stuff = await aiohttp.request('GET', url)
        cache[url] = stuff
        return stuff
另一件需要注意的事情是,当一个协程在
get\u stuff
内部时,进行
aiohttp
调用,另一个等待
stuff\u lock
,第三个协程根本不需要调用
get\u stuff
也可以运行,而不受
lock
上的协程阻塞的影响


显然,这个例子有点做作,但希望它能让您了解为什么
asyncio.Lock
会有用;它允许您保护一个关键部分,而不阻止其他不需要访问该关键部分的协同程序的运行。

一个例子是,您只希望某些代码运行一次,但许多人却请求它(例如,在web应用程序中)


这是一把锁,不确定它与先占权有什么关系,当你试图获得一把锁时,你会特别放弃控制权,希望它会在你持有锁的情况下还给你。这是为了有一个关键部分,一个协同程序一次可以进入。都在文件里。我想你要么仔细阅读官方文件,要么不理解这个问题。谢谢你的详细解释。让我来总结一下(对于不理解这个问题的人)。1) 协同程序不能被抢占——它们运行直到“屈服于”将控制返回到循环。2) Lock()用于保护调用“yield from”的关键部分,否则无需使用锁。讨论是在单线程异步IO使用模式的假设下进行的。作为dano给出的一个很好的例子,我必须重复我在问题中所说的——我个人不喜欢在关键部分使用“yield from”的想法。这听起来无关紧要,但我不得不说。dano-在这个特定的示例中(请记住,它确实是人为设计的),如果您只是从
中删除
产量并发出阻塞HTTP请求,您不会获得同等的性能吗?因为按照现在的锁定方式,只有一个
get_stuff()
的实例会进行。(如中所示,实例B只能在实例A完全完成时启动。)@NickChammas如果整个应用程序中运行的唯一协程正在等待
get_stuff
,那么性能将相当。但是如果您有其他的协同程序运行其他不需要锁的方法,那么没有;阻止HTTP请求将阻止所有其他协同路由,从而完全停止应用程序,直到它完成。使用
asyncio.Lock
允许所有其他协同程序继续运行。@SamanthaAtkins它们不能并行运行,但可以并发运行。我的回答再次给出了一个用例,其中没有锁定的并发执行会导致意外行为。
async def request_by_many():
    key = False
    lock = asyncio.Lock()
    async with lock:
        if key is False:
            await only_run_once()

async def only_run_once():
    while True:
        if random()>0.5:
            key = True
            break
        await asyncio.sleep(1)