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 在并发任务之间共享资源的主要内容,如果未能解决你的问题,请参考以下文章

Asyncio之EventLoop笔记

如何使用 python 的 asyncio 模块正确创建和运行并发任务?

asyncio--python3未来并发编程主流充满野心的模块

python协程(4):asyncio

asyncio:异步I/O事件循环和并发工具(持续跟新中)

如何在 Python 3.8 中为 asyncio.gather 构建任务列表