DotNet高性能设备索引实现(多线程安全+效率)
Posted 何以解忧 `唯有暴富
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DotNet高性能设备索引实现(多线程安全+效率)相关的知识,希望对你有一定的参考价值。
代码下载地址
https://download.csdn.net/download/g313105910/18464759
多线程通过字典进行设备查找,主键key使用Guid,也可以用设备唯一Id去替换,最关键的是string,string是不可变字符对象(多线程安全+效率:只用复制地址)
首先先讲一下string
string和String效果相同,MSDN中对string的说明:string is an alias for String in the .NET Framework。string是String的别名而已,string是c#中的类,String是Framework的类,C# string 映射为 Framework的 String。如果用string,编译器会把它编译成String,所以如果直接用String就可以让编译器少做一点点工作。
为什么String是不可变字符对象呢?有什么好处呢? 不可变对象,顾名思义就是创建后不可以改变的对象。
String s = “ABC”; s.toLowerCase(); 如上s.toLowerCase()并没有改变“ABC“的值,而是创建了一个新的String类“abc”,然后将新的实例的指向变量s。 相对于可变对象,不可变对象有很多优势:
1).不可变对象可以提高String Pool的效率和安全性。如果你知道一个对象是不可变的,那么需要拷贝这个对象的内容时,就不用复制它的本身而只是复制它的地址,复制地址(通常一个指针的大小)需要很小的内存效率也很高。对于同时引用这个“ABC”的其他变量也不会造成影响。
2).不可变对象对于多线程是安全的,因为在多线程同时进行的情况下,一个可变对象的值很可能被其他进程改变,这样会造成不可预期的结果,而使用不可变对象就可以避免这种情况。 String是所有语言中最常用的一个类。我们知道在Java中,String是不可变的、final的。Java在运行时也保存了一个字符串池(String pool),这使得String成为了一个特别的类。
测试程序的流程图
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadTest
{
class Program
{
static string GuidStr = "";
static Dictionary<string, DataCache> Datas = new Dictionary<string, DataCache>();
static void Main(string[] args)
{
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 10000; i++)
{
GuidStr = Guid.NewGuid().ToString();
DataCache dataCache = new DataCache() { Name = GuidStr, Value = "123456789" };
DataCache tempDataCache;
if (Datas.TryGetValue(GuidStr, out tempDataCache))
{
Datas[GuidStr] = dataCache;
}
else
{
Datas.Add(GuidStr, dataCache);
}
}
for (int i = 0; i < 1000; i++)
{
Thread thread = new Thread(Check);
thread.Start();
threads.Add(thread);
}
for (int i = 0; i < 10; i++)
{
Thread thread = new Thread(Amend);
thread.Start();
threads.Add(thread);
}
Thread.Sleep(10000);
foreach(var thread in threads)
{
try
{
thread.Abort();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Console.WriteLine("Exit");
}
public static void Amend()
{
while(true)
{
DataCache dataCache = Get(GuidStr);
if (dataCache != null)
{
dataCache.Value = "123456789";
}
Thread.Sleep(1000);
if (dataCache != null)
{
dataCache.Value = "987654321";
}
Thread.Sleep(1000);
if (dataCache != null)
{
dataCache.IsDelete = true;
}
Thread.Sleep(1000);
if (dataCache != null)
{
dataCache.IsDelete = false;
}
Thread.Sleep(1000);
}
}
public static void Check()
{
while (true)
{
DataCache dataCache = Get(GuidStr);
if (dataCache != null)
{
if(dataCache.IsDelete == true)
{
Console.WriteLine("IsDelete == True");
}
else
{
if (dataCache.Value == "123456789")
{
Console.WriteLine("IsDelete == False,Value == 123456789");
}
else if (dataCache.Value == "987654321")
{
Console.WriteLine("IsDelete == False,Value == 987654321");
}
else
{
Console.WriteLine("Error");
}
}
}
else
{
Console.WriteLine("dataCache == null");
}
Thread.Sleep(10);
}
}
public static DataCache Get(string guidStr)
{
DataCache dataCache;
if (Datas.TryGetValue(guidStr, out dataCache))
{
return dataCache;
}
else
{
return null;
}
}
}
public class DataCache
{
public string Name { get; set; }
public string Value { get; set; }
public bool IsDelete { get; set; }
//public String Value { get; set; }
}
}
以上是关于DotNet高性能设备索引实现(多线程安全+效率)的主要内容,如果未能解决你的问题,请参考以下文章
VectorArrayListLinkedList在存储结构和存取性能上的区别
dotnet ConcurrentDictionary 的 GetOrAdd 性能比 TryGetValue 加 TryAdd 低