什么';的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)