When looking into IsEmpty, I noticed this on MSDN:
However, as this collection is intended to be accessed concurrently, it may be the case that another thread will modify the collection after IsEmpty returns, thus invalidating the result.
Sure this is true, but does this also imply that ConcurrentQueue doesn't use a read barrier when checking if the queue is empty?
I want to have a piece of code that checks in another thread if the concurrent queue is empty. Something like this:
while (!queue.IsEmpty)
{
}
However.. if ConcurrentQueue doesn't use a read barrier, I'd say we need to add our own memory barrier to ensure we read the right data, like this:
Thread.MemoryBarrier();
while (!queue.IsEmpty)
{
Thread.MemoryBarrier();
}
(BTW: These are just a minimal example to illustrate the case, there's more code in reality).
Is my observation correct? Or does the ConcurrentQueue handle this and does the first implementation work? (e.g. what I would expect from 'Concurrent')?
And what about 'Count'? I can't find the answer on MSDN... Same story?
No, it's nothing to do with memory barriers. It's simply got to be the case that something else could nip in and add or remove something to or from the queue just after your test.
You shouldn't really use IsEmpty. Use TryDequeue instead. Or use a BlockingCollection.
You really don't want to start writing code that "locks" the queue while you mess around with IsEmpty or Count.
(I almost never use ConcurrentQueue nowadays, since BlockingCollection is so much better, although that does of course depend on what you're trying to do.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With