San*_*Kim 7 python thread-safety python-3.x python-asyncio
简单地说,thread-safe意味着当多个人thread访问相同的资源并且我知道从根本上Asyncio使用一个时是安全的thread。
但是,不止一个人Asyncio Task可以同时多次访问资源,例如multi-threading.
例如数据库连接(如果对象不是thread-safe并且支持Asyncio操作)。
Task A和Task B访问同一个数据库对象。Task A。Task A await DB对象上的IO操作。(需要很长时间)Task BStep3的 IO 操作仍在进行中(未完成)。Task B await 对同一个 DB 对象的 IO 操作。Task B试图一次访问同一个对象。它是完全Asyncio安全的吗?如果是,它是如何保证安全的?
Using the same asyncio object from multiple tasks is safe in general. As an example, aiohttp has a session object, and it is expected for multiple tasks to access the same session "in parallel".
if so, what does it make safe?
The basic architecture of asyncio allows for multiple coroutines to await a single future result - they will simply all subscribe to the future's completion, and all will be scheduled to run once the result is ready. And this applies not only to coroutines, but also to synchronous code that subscribes to the future using add_done_callback.
That is how asyncio will handle your scenario: tasks A and B will ultimately subscribe to some future awaited by the DB object and. Once the result is available, it will be delivered to both of them, in turn.
Pitfalls typically associated with multi-threaded programming do not apply to asyncio because:
Unlike with threads, it is very predictable where a context switch can occur - just look at await statements in the code (and also async with and async for - but those are still very visible keywords). Anything between them is, for all intents and purposes, atomic. This eliminates the need for synchronization primitives to protect objects, as well as the mistakes that result from mishandling such tools.
All access to data happens from the thread that runs the event loop. This eliminates the possibility of a data race, reading of shared memory that is being concurrently written to.
One scenario in which multi-tasking could fail is multiple consumers attaching to the same stream-like resource. For example, if several tasks try to await reader.read(n) on the same reader stream, exactly one of them will get the new data1, and the others will keep waiting until new data arrives. The same applies to any shared streaming resource, including file descriptors or generators shared by multiple objects. And even then, one of the tasks is guaranteed to obtain the data, and the integrity of the stream object will not be compromised in any way.
1一个接收数据的任务仅适用于任务共享阅读器并且每个任务单独调用的情况data = await reader.read(n)。如果要使用(不使用)提取未来,在多个任务之间共享未来,并在每个任务中等待它,所有任务都将收到最终由该未来返回的特定数据块的通知。fut = asyncio.ensure_future(reader.read(n))awaitdata = await fut