I have saw some code that use asyncio
as a asynchronous task queue. Maybe like following
async def _send_email(address):
pass
def send_email(address):
task = asyncio.tasks.ensure_future(_send_email(address))
task.add_done_callback(callback)
def init_worker(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
@app.route("/notify")
def do_jobs():
# some code
loop.call_soon_threadsafe(send_email, address)
loop = asyncio.new_event_loop()
worker = threading.Thread(target=init_worker, args=(loop,))
worker.setDaemon(True)
worker.start()
app.run()
I read the implementation of call_soon_threadsafe
. It will append the task to loop._ready
, the code here.
self._ready.append(handle)
But when the sub thread is executing _run_once
, and pop the task from loop._ready
, the code here.
handle = self._ready.popleft()
I'm not sure if the race condition exists or not. If it does not exist, under what circumstances should use the queue.Queue
?
Forgive my poor English.
asyncio primitives are not thread-safe, therefore they should not be used for OS thread synchronization (use threading for that);
Asynchronous programming is a programming paradigm that enables better concurrency, that is, multiple threads running concurrently. In Python, asyncio module provides this capability. Multiple tasks can run concurrently on a single thread, which is scheduled on a single CPU core.
One of the cool advantages of asyncio is that it scales far better than threading . Each task takes far fewer resources and less time to create than a thread, so creating and running more of them works well. This example just creates a separate task for each site to download, which works out quite well.
What's different to threading is that, asyncio is single-process and single-thread. There is an event loop in asyncio which routinely measure the progress of the tasks. If the event loop has measured any progress, it would schedule another task for execution, therefore, minimizing the time spent on waiting I/O.
As per https://bugs.python.org/issue15329#msg199368:
The deque's append(), appendleft(), pop(), popleft(), and len(d) operations are thread-safe in CPython.
And there's info about Queue in the same message:
So, is deque a faster replacement for Queue.Queue or not?
Yes, it is faster. The Queue module itself uses the deque internally. And the Queue is slowed down a bit through locks, function indirection, and additional features such as maxsize, join, and task_done.
deque
is just a datastructure, but Queue (and asyncio.Queue as well) provide much more, allowing for more flexible control flow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With