仅当满足条件时才从 ConcurrentQueue 出列

Hug*_*une 6 c# queue concurrency multithreading locking

ConcurrentQueue仅当满足某些条件时,如何才能将 a 的下一个元素出队?

例如,如果下一个要出列的项目满足特定条件,则将其出列,否则保留它。本质上是一个'DequeueIf'or'TryDequeueIf'方法

例子:

var myQueue = new ConcurrentQueue<int>()
...
int item;
// only dequeue if the next item is 0
bool success = myQueue.TryDequeueIf(out item, x=>x==0) 
Run Code Online (Sandbox Code Playgroud)

当然可以先调用TryPeek,检查条件,然后再调用TryDequeue,但这不再是线程安全的。

我可以将整个封装TryPeek & TryDequeue在一个锁中,但这有点违背了使用 ConcurrentQueue 的目的;并意味着所有常规无条件出队也必须被锁定。我不确定我是否需要锁定每一个Enqueue才能保存。如果可能的话,我想避免实现我自己的锁定策略时可能遇到的陷阱。

ConcurrentQueue是否有使用 .net4.0类或其他并发类之一的无锁解决方案?

usr*_*usr 5

使用内置方法这是不可能的。该怎么办?

  1. 编写您自己的简单队列。只需对每个队列使用一个锁即可。除非队列中的流量非常高,否则效果会很好。无竞争锁每个周期消耗两个互锁操作。
  2. 使用互锁操作编写复杂的队列。使用 CAS 重试循环,您可以实现谓词原子 take 操作。您可能可以使用 BCL 源代码作为起点或灵感。
  3. 放弃排队的想法。在非队列上执行此操作很容易。如果您绘制了错误的项目,只需将其插回到队列中即可。