Python3 Asyncio 在并发任务之间共享资源
Posted
技术标签:
【中文标题】Python3 Asyncio 在并发任务之间共享资源【英文标题】:Python3 Asyncio shared resources between concurrent tasks 【发布时间】:2016-08-05 11:20:10 【问题描述】:我有一个用 Python3.5 编写的网络应用程序,它利用 pythons Asyncio 同时处理每个传入连接。
在每个并发连接上,我想将连接的客户端数据存储在一个列表中。我担心如果两个客户端同时连接(这是可能的),那么两个任务都会尝试同时写入列表,这肯定会引发问题。我将如何解决这个问题?
【问题讨论】:
如果您使用 HTTP,您应该使用aiohttp
,它 (AFAIK) 会为您处理所有这些。
【参考方案1】:
asyncio 仅在 yield 点(await
表达式)上进行上下文切换,因此两个并行任务不会在相同时间执行。
但如果仍然可能出现竞争条件(这取决于具体的代码结构),您可以使用asyncio synchronization primitives 和queues。
【讨论】:
每个客户端连接都由一个单独的任务处理。在每个任务中,当客户端被处理时,数据被附加到一个全局列表中。task = asyncio.Task(self._handle_client(client_reader, client_writer)) self.clients[task] = (client_reader, client_writer)
和 _handle_client
内的列表被附加到。如果两个客户端同时连接,这会导致问题吗?
不,很安全。【参考方案2】:
您的问题中缺少很多信息。
您的应用程序是否线程化?如果是,那么您必须将您的列表包含在threading.Lock
中。
您是否在请求处理程序的写入(到列表)之间切换上下文(例如使用await
)?如果是,那么您必须将您的列表包含在 asyncio.Lock
中。
您是否进行多处理?如果是,那么您必须使用multiprocessing.Lock
您的应用程序是否划分到多台机器上?然后你必须使用一些外部共享数据库(例如 Redis)。
如果所有这些问题的答案都是否,那么您无需执行任何操作,因为单线程异步应用无法并行更新共享资源。
【讨论】:
以上是关于Python3 Asyncio 在并发任务之间共享资源的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 python 的 asyncio 模块正确创建和运行并发任务?