为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
白衣非少年 2023-05-13 16:04:46
我在 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 次调用使用一次锁我想看看是否有办法移除锁,但这主要是因为我认为必须有一个更好的解决方案来双重检查。我一直在考虑的另一种方法是提前创建空箱子,这将完全消除对任何锁的需求,但搜索正确的箱子会变得更慢,因为它必须扫描预建箱子列表才能找到正确的那个。
查看完整描述

1 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

使用ConcurrentDictionarycan 解决您遇到的问题。在这里,我假设您的属性是双精度类型TimeStamp,但它可以是任何类型,只要您使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;

        }

    }

}


查看完整回答
反对 回复 2023-05-13
  • 1 回答
  • 0 关注
  • 185 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信