首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >尝试为C#并发队列找到无锁解决方案

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

Stack Overflow用户
提问于 2019-06-28 01:44:09
回答 1查看 438关注 0票数 1

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

代码语言:javascript
运行
复制
        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秒间隔的存储箱(Store objects)中。这些bin在写入时位于队列中,而在处理和写入数据时,队列将被清空。

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

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

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

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

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

我一直在考虑的另一种选择是提前创建空的回收站,这将完全消除对任何锁的需求,但搜索正确的回收站将变得更慢,因为它将不得不扫描列表中的预置回收站来找到适当的回收站。

EN

Stack Overflow用户

回答已采纳

发布于 2019-06-28 02:10:02

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

代码语言:javascript
运行
复制
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;
        }
    }
}
票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56796250

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档