Is Queue.Queue.queue.clear() thread-safe?

Tim Peters tim.peters at gmail.com
Thu Jun 22 17:40:21 EDT 2006


[Russell Warren]
> I'm guessing no, since it skips down through any Lock semantics,

Good guess :-)  It's also unsafe because some internal conditions must
be notified whenever the queue becomes empty (else you risk deadlock).

> but I'm wondering what the best way to clear a Queue is then.
>
> Esentially I want to do a "get all" and ignore what pops out, but I
> don't want to loop through a .get until empty because that could
> potentially end up racing another thread that is more-or-less blindly
> filling it asynchronously.
>
> Worst case I think I can just borrow the locking logic from Queue.get
> and clear the deque inside this logic, but would prefer to not have to
> write wrapper code that uses mechanisms inside the object that might
> change in the future.

There's simply no defined way to do this now.

> Also - I can of course come up with some surrounding architecture to
> avoid this concern altogether, but a thread-safe Queue clear would do
> the trick and be a nice and short path to solution.
>
> If QueueInstance.queue.clear() isn't thread safe... what would be the
> best way to do it?  Also, if not, why is the queue deque not called
> _queue to warn us away from it?

"Consenting adults" -- if you want an operation that isn't supplied
out of the box, and are willing to take the risk of breaking into the
internals, Python isn't going to stop you from doing whatever you
like.  "mutex" isn't named "_mutex" for the same reason.  A

    q.mutex.acquire()
    try:
       q.queue.clear()
       q.unfinished_tasks = 0
       q.not_full.notify()
       q.all_tasks_done.notifyAll()
    finally:
       q.mutex.release()

sequence probably works (caveat emptor).  BTW, it may be _possible_
you could use the newer task_done()/join() Queue gimmicks in some way
to get what you're after (I'm not really clear on that, exactly).

Anyway, yes, there is cross-release risk in breaking into the
internals like that.  That's an "adult decision" for you to make.  The
only way to get permanent relief is to re-think your approach, or
propose adding a new Queue.clear() method and Queue._clear() default
implementation.  I don't know whether that would be accepted -- it
seems simple enough, although since you're the first person to ask for
it 15 years :-), you won't get much traction arguing that's a critical
lack, and every new bit of cruft becomes an ongoing burden too.



More information about the Python-list mailing list