如何解决当不同事件循环中的协程访问通用代码时,是否需要使用asyncio.Lock?
背景
我继承了使用多个事件循环来处理对使用websockets.serve创建的多个对象的读写的代码。这些协程需要访问公共列表。
场景
- 事件循环X中的协程A
- 事件循环Y中的协程B
问题
- 我需要保护对公用列表的访问吗?
- 如果我确实需要保护对列表的访问,那么asyncio.Lock()是否足够?
解决方法
我假设事件循环是并行运行的,每个循环都在其自己的线程中。在这种情况下,您将完全像对待不同线程之间共享的数据那样对待共享数据。具体来说:
-
这取决于您对列表的处理方式。如果一个线程正在读取而另一个线程正在调用类似
append
的线程,则您不需要同步,因为您受到了GIL的保护。但是,如果您正在做更复杂的事情,例如删除读取器线程指示的项目,您将需要锁定以确保不会因并发修改而丢失项目。 -
asyncio.Lock
绝对不是不是正确使用的锁定设备,因为它是为在一个事件循环(即单线程)中使用而设计的。您也不能使用threading.Lock
,因为它是非异步的并且会阻塞整个事件循环。您可能可以使用loop.call_soon_threadsafe
在事件循环之间进行同步,但这并不简单。
您继承的代码使用asyncio的方式不适合您使用,并且您很可能会遇到问题。由于asyncio事件循环旨在扩展到任意数量的任务,因此我建议将代码重构为使用单个事件循环。然后,您将不需要特殊的同步,因为等待之间的任何代码自然会形成一个关键部分,并且如果您需要在等待之间进行锁定,则可以使用针对该用例创建的asyncio.Lock
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。