Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
试图为C#并发队列找到无锁解决方案_C#_Concurrency_Locking - Fatal编程技术网

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

试图为C#并发队列找到无锁解决方案,c#,concurrency,locking,C#,Concurrency,Locking,我在C#中有以下代码: (\u StoreQueue是一个ConcurrentQueue) 系统实时收集数据(相当高的频率,大约300-400次呼叫/秒),并将其放入表示5秒间隔的容器(存储对象)中。这些容器在写入时处于队列中,而在处理和写入数据时,队列将清空 因此,当数据到达时,将进行检查,以查看是否存在该时间戳的bin(四舍五入为5秒),如果没有,则创建一个bin 由于这是一个非常多线程的系统,因此系统遵循以下逻辑: 如果有一个箱子,它用来放置数据。 如果没有bin,则会启动一个锁,并在该锁

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

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

因此,当数据到达时,将进行检查,以查看是否存在该时间戳的bin(四舍五入为5秒),如果没有,则创建一个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;
        }
    }
}
类程序
{
ConcurrentDictionary _StoreQueue=新建ConcurrentDictionary();
静态void Main(字符串[]参数)
{
var T=17d;
//如果未退出商店,请尝试添加17
_GetOrAdd(T,新存储(T));
}
公共类商店
{
公共双时间戳{get;set;}
公共存储(双时间戳)
{
时间戳=时间戳;
}
}
}

System.Collections.Concurrent.ConcurrentQueue
不工作?已经有一个并发队列数据结构,它是一个并发队列,但问题是如果两个线程同时尝试写入,一个线程可能正在创建一个bin,而另一个线程的bin检查失败(它也将创建一个bin);我刚刚编辑了这个问题,说明这是一个ConcurrentQueue,因为这不清楚。您可以使用ConcurrentQueue,但不能在排队之前聚合存储区中的数据。如果让队列数据的使用者将数据聚合为5秒钟的数据包,那么锁定问题就会消失。(假设您收集的数据量没有造成过度的内存压力)为什么还要使用
ConcurrentQueue
ConcurrentDictionary
可以解决您的问题,只需使用一行即可。关键是
Store.TimeStamp
的值类型,该值是
Store
object。elgonzo的解决方案是可行的,但它需要在所有地方进行大量更改。字典不会引起类似的问题吗:一个线程没有找到密钥,创建了存储,在创建并添加到字典之前,另一个线程没有找到密钥,也没有创建自己的密钥?
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;
        }
    }
}