简单地说,thread-safe
意味着当多个thread
访问同一个资源时,它是安全的,我知道Asyncio
基本上使用一个thread
。在
但是,不止一个Asyncio Task
可以像multi-threading
那样一次多次访问一个资源。在
例如DB connection(如果对象不是thread-safe
,并且支持Asyncio
操作)。在
Task A
和{Task A
。在Task A
await
对DB对象执行IO操作。(这将花费足够长的时间)Task B
Step3
的IO操作仍在进行中(未完成)。在Task B
await
对同一DB对象执行IO操作。在Task B
正试图一次访问同一对象。在它在Asyncio
中是完全安全的吗?如果是,它又有什么安全性?在
从多个任务使用同一个asyncio对象通常是安全的。例如,aiohttp有一个session对象,多个任务应该“并行”访问同一个会话。在
asyncio的基本架构允许多个协程来
await
一个单独的未来结果-它们将简单地全部订阅未来的完成,并且所有的都将被调度在结果准备好之后运行。这不仅适用于协同程序,也适用于使用add_done_callback
订阅未来的同步代码。在这就是asyncio将如何处理您的场景:任务A和B最终将订阅DB对象和等待的某个未来。一旦结果可用,它将依次传递给他们两个。在
通常与多线程编程相关的陷阱不适用于asyncio,因为:
与线程不同,上下文切换的位置是非常可预测的——只需查看代码中的}-但这些仍然是非常可见的关键字)。他们之间的任何东西,无论出于什么目的,都是原子的。这样就不需要同步原语来保护对象,也消除了由于错误处理这些工具而导致的错误。
await
语句(以及async with
和{所有对数据的访问都是从运行事件循环的线程进行的。这就消除了并发写入的共享内存的数据争用的可能性。
多任务处理可能失败的一种情况是多个使用者附加到同一个流式资源。例如,如果多个任务试图在同一个
reader
流上等待reader.read(n)
,那么其中一个任务将获得新数据1,而其他任务将一直等待,直到新数据到达。这同样适用于任何共享流资源,包括多个对象共享的文件描述符或生成器。即使这样,其中一个任务也能保证获得数据,流对象的完整性也不会以任何方式受到损害。在1只有当任务共享读卡器并且每个任务分别调用
data = await reader.read(n)
时,一个接收数据的任务才适用。如果要使用fut = reader.read(n)
(不带使用await
)提取一个未来,那么在多个任务中共享未来,并用data = await fut
在每个任务中等待它,则所有任务都将收到由该未来返回的特定数据块的通知。不,asyncio不是线程安全的。通常只有一个线程可以控制事件循环和/或与事件循环关联的资源。如果其他线程想访问它,它应该通过特殊的方法来访问它,比如
call_soon_threadsafe
。在相关问题 更多 >
编程相关推荐