试图为 C# 并发队列找到无锁解决方案

Trying to find a lock-less solution for a C# concurrent queue

我在 C# 中有以下代码: (_StoreQueue 是一个 ConcurrentQueue)

        var S = _StoreQueue.FirstOrDefault(_ => _.TimeStamp == T);
        if (S == null)
        {
            lock (_QueueLock)
            {
                // try again
                S = _StoreQueue.FirstOrDefault(_ => _.TimeStamp == T);
                if (S == null)
                {
                    S = new Store(T);
                    _StoreQueue.Enqueue(S);
                }
            }
        }

系统正在实时收集数据(相当高的频率,大约 300-400 次调用/秒)并将其放入表示 5 秒间隔的容器(存储对象)中。这些 bin 在写入时处于队列中,并且在处理和写入数据时队列被清空。

因此,当数据到达时,会检查是否有该时间戳的 bin(四舍五入 5 秒),如果没有,则会创建一个。

由于这是相当多线程的,系统遵循以下逻辑:

如果有bin,就是用来放数据的。 如果没有 bin,将启动一个锁,并在该锁内再次进行检查以确保它不是由另一个线程同时创建的。如果仍然没有 bin,则会创建一个。

使用这个系统,锁大约每2k次调用使用一次

我正在尝试查看是否有解除锁定的方法,但这主要是因为我认为必须有一个更好的解决方案来双重检查。

我一直在考虑的另一种方法是提前创建空箱子,这将完全消除对任何锁的需要,但搜索正确的箱子会变慢,因为它必须预先扫描列表-建立垃圾箱以找到合适的垃圾箱。

使用 ConcurrentDictionary 可以解决您遇到的问题。在这里,我假设您的 TimeStamp 属性 类型为 double 但它可以是任何类型,只要您使 ConcurrentDictionary 键与类型匹配。

class Program
{
    ConcurrentDictionary<double, Store> _StoreQueue = new ConcurrentDictionary<double, Store>();

    static void Main(string[] args)
    {
        var T = 17d;

        // try to add if not exit the store with 17
        _StoreQueue.GetOrAdd(T, new Store(T));
    }
    public class Store
    {
        public double TimeStamp { get; set; }
        public Store(double timeStamp)
        {
            TimeStamp = timeStamp;
        }
    }
}