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

Tim Peters tim.peters at gmail.com
Thu Jun 22 20:40:15 EDT 2006


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

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

[Fredrik Lundh]
> "also" ?  if it weren't for the other things, the clear() call itself
> would have been atomic enough, right ?

Define "other things" :-)  For example, Queue.get() relies on that
when self._empty() is false, it can do self._get() successfully.
That's 100% reliable now because the self.not_empty condition is in
the acquired state across both operations.  If some yahoo ignores the
underlying mutex and clears the queue after self._empty() returns true
but before pop() executes self._get(), the call to the latter will
raise an exception.  That kind of failure is what I considered to be
an instance of a problem due to the OP's "skips down through any Lock
semantics"; the failure to notify internal conditions that the queue
is empty is a different _kind_ of problem, hence my "also" above.

If you're just asking whether deque.clear() is "atomic enough" on its
own, define "enough" :-)  It has to decref each item in the deque, and
that can end up executing arbitrary Python code (due to __del__
methods or weakref callbacks), and that in turn can allow the GIL to
be released allowing all other threads to run, and any of that
Python-level code may even mutate the deque _while_ it's being
cleared.

The C code in deque_clear() looks threadsafe in the sense that it
won't blow up regardless -- and that's about the strongest that can
ever be said for a clear() method.  dict.clear() is actually a bit
stronger, acting as if a snapshot were taken of the dict's state at
the instant  dict.clear() is called.  Any mutations made to the dict
as a result of decref side effects while the original state is getting
cleared survive.  In contrast, if a new item is added to a deque d
(via decref side effect)  while d.clear() is executing, it won't
survive.  That's "atomic enough" for me, but it is kinda fuzzy.



More information about the Python-list mailing list