Search code examples
pythontornado

Are single producer/consumer Tornado queues thread-safe?


Almost nothing in Tornado is thread-safe. There is good reason for this.

Threadsafe queues in particular would incur unnecessary expense. However, thread-safety for queues can mean a variety of things, common use implies the hard multi-producer, multi-consumer case.

However, a far simpler case is the single-producer, single-consumer case. Is the following pair of operations safe with Tornado?

# on event loop in Thread 1
yield queue.get()  

# In normal code in Thread 2
queue.put_nowait(msg)  

Solution

  • No, Tornado queues are not thread safe by any definition of the term. Consider scheduling the "put_nowait" call on the main thread from your "Thread 2":

    IOLoop.current().add_callback(queue.put_nowait, msg)
    

    Here is the doc for add_callback:

    It is safe to call this method from any thread at any time, except from a signal handler. Note that this is the only method in IOLoop that makes this thread-safety guarantee; all other interaction with the IOLoop must be done from that IOLoop‘s thread. add_callback() may be used to transfer control from other threads to the IOLoop‘s thread.

    If the queue has a maximum size configured then put_nowait may raise an exception and lose the "msg" element. But if there is no max size this technique should work for you.