Issue
Simply speaking, thread-safe
means that it is safe when more than one thread
access the same resource and I know Asyncio
use a single thread
fundamentally.
However, more than one Asyncio Task
could access a resource multiple time at a time like multi-threading
.
For example DB connection(if the object is not thread-safe
and supports Asyncio
operation).
- Schedule
Task A
andTask B
accessing the same DB object. - IO Loop executes
Task A
. Task A
await
IO operation on the DB object.(it will take long time enough)- IO Loop executes
Task B
Step3
's IO operation is still in progress(not done).Task B
await
IO operation on the same DB object.- Now
Task B
is trying to access the same object at a time.
Is it completely safe in Asyncio
and if so, what does it make safe?
Solution
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 alsoasync with
andasync 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 One task receiving the data only applies if the tasks share the reader and each task separately calls data = await reader.read(n)
. If one were to extract a future with fut = asyncio.ensure_future(reader.read(n))
(without using await
), share the future among multiple tasks, and await it in each task with data = await fut
, all tasks would be notified of the particular chunk of data that ends up returned by that future.
Answered By - user4815162342
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.