Queue qsize = unreliable?

Dave Brueck dave at pythonapocrypha.com
Mon Aug 9 17:11:32 CEST 2004


Ames Andreas (MPA/DF) wrote:
> Jeff Shannon wrote:
> 
>>No you don't.  You simply execute a non-blocking get(), and be
>>prepared to catch the Queue.Empty exception.  Similarly, if you want
>>a non-blocking producer, then you execute a non-blocking put() and
>>catch the Queue.Full exception.
> 
> I've actually read the docs some time ago, but I've also read the
> source.  I think the problem is here that "non-blocking" isn't very
> well defined.

I assume it means "non-blocking from the caller's perspective" (see below).

> In the sense that the consumer won't wait until something gets
> available from an empty Queue you are absolutely right with calling
> Queue.get(False).  But if you look at the source you will find that
> the first thing that's done in Queue.get() is aquiring a mutex/cv
> lock.  That's potentially quite blocking as far as I am concerned.

But is it blocking in any way that you (the caller) will likely notice? 
(probably not - the mutex is held for a relatively short period of time. 
Note also that the mutex that gets acquired is not the "main" mutex of 
the Queue.)

> With CPython's assertions about atomicity of certain list operations
> it's possible to implement a lock free queue that is even usable for
> the single producer or single consumer case.

If you have the single producer and/or single consumer case, you don't 
need a Queue at all - just use a built-in list (or in 2.4 a 
collections.deque object).

>>That's really the only reliable way to tell whether the queue is
>>empty or full, anyhow...
> 
> 
> I don't understand why this is more reliable than what I described in
> my scenario.  If, for example, you have a single consumer then:
> 
> if !q.empty():
>    reliableCode()
> else
>    unreliableCode()
> 
> should be absolutely okay.

It'd probably _work_, yes, but would it offer any real advantage? On 
that particular mutex, there's almost never any contention at all - 
*especially* in e.g. the single consumer case. And, even if there is 
some contention, it is acquired for an extremely short amount of time 
(relatively speaking) - which is why the caller is not likely to notice 
that any locking is going on under the covers. The cost of having both 
reliableCode and unreliableCode paths seems to outweigh any potential 
advantage IMO.

-Dave



More information about the Python-list mailing list