Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is python asyncio call_soon_threadsafe really thread-safe?

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.

like image 808
Hanaasagi Avatar asked Dec 16 '17 15:12

Hanaasagi


People also ask

Is Asyncio thread-safe?

asyncio primitives are not thread-safe, therefore they should not be used for OS thread synchronization (use threading for that);

Is Python Asyncio multithreaded?

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.

Why is Asyncio better than threading?

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.

Is Asyncio single threaded?

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.


1 Answers

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.

like image 164
leovp Avatar answered Oct 09 '22 11:10

leovp