Search code examples
c#concurrencylanguage-agnosticproducer-consumerconcurrent-queue

Pattern to remove elements from ConcurrentQueue after peeking


I have one producer and multiple consumers. I am using ConcurrentQueue. I am using C# but I think my problem is language agnostics.

There can be non-unique consumers. i.e. more than one consumers can be interested in same message. So, non-unique consumers are like workers-of-one-kind.

There are unique consumers as well and since they are dealing with a queue, they assume ordering in messages.

Problem:

When a consumer Guid-1-worker-1 peek into the queue and finds a message M1 for itself, it will dequeue it. However, because of concurrency, message M1 might have been dequeued by worker Guid-1-worker-2. At this time, message dequeued by Guid-1-worker-1 is for Guid-2. Guid-2 has only one worker and hence, putting the message back in queue does not help as it breaks the ordering of messages.

What I want is that if I have looked at a message, then only i should be able to dequeue it. Now, I think I have to use lock here. But simple List will work instead of ConcurrentQueue as well.

Is there any other data structure that provides : Peek-Check-Dequeue kind of concurrent semantics ?

Is there any other way to model the problem ?


Solution

  • Peek-Check-Dequeue forces some kind of lock. Either you lock yourself of the data structure performs the locking (it would need to lock, then call into your code to perform the check, then unlock).

    There is nothing built-in or commonly used to help with this. Just do the locking yourself.

    If you have a very high frequency of such operations (millions per second) then locking overhead becomes an issue. At that point you'd need a more clever design. That would be more work and more risk for bugs.