What you don't know about Dictionary and ConcurrentDictionary

When working on a project recently, Dictionarywhen using global variables in multi-threading, I found that the data was not stored in it Dictionary, but the program did not report an error. After some investigation, I found that Dictionary is a non-thread-safe type, so I feel that the data is not The reason for writing it in is that when multiple threads compete for global variables, the data is not written, so I went to have a Dictionarycareful understanding of it.
After checking the information on the Internet, I found that the most explained are Dictionary(non-thread-safe) and ConcurrentDictionary(thread-safe), so I also explained these two keywords carefully, and by the way, I also got a deeper understanding of them.
DictionaryHow to solve the thread safety problem? You can use locks, thread global variables, use, ConcurrentDictionaryetc. Let's take a look together, Let's go.

Dictionary

Dictionary<TKey, TValue>The generic class provides a key-value pair mapping. TKeyThe speed of retrieving values ​​through it is very fast, and the time complexity is close to O(1). This is because it is Dictionaryimplemented through a hash table, which is a disguised form HashTableand adopts the data of the separated link hash table structure to solve the hash collision problem.
In earlier versions of C#, you could use a collection initializer for sequence-style collections, obtained by adding parentheses around key-value pairs, Dictionary<TKey, TValue>as in:

Dictionary<int, string> msgs = new Dictionary<int, string>()
{
    
    
    {
    
     1, "Hello, "},
    {
    
     2 , "World"},
    {
    
     3, "!"}
};

The new syntax supports assigning to collections using indexes, such as:

Dictionary<int, string> MsgErrs = new Dictionary<int, string>()
{
    
    
    [1] = "Hello, ",
    [2] = "World",
    [3] = "!",
};

keyThe above two are similar in initialization assignment, but there are still some differences between the two. The former will report an error directly if there are duplicate values ​​during initialization . When the latter is initialized, keythere can be duplicate values, the system will automatically filter out duplicate keyvalues, and the program will not report an error.
Implementing a collection of key/value pairs.
Each addition to the dictionary contains a value with its associated value, which is conveniently retrieved by using the key;
if you use the collection initializer to generate Dictionarythe collection, you can use the following method:

public static Dictionary<string, Element> BuildDic()
        {
    
    
 return new Dictionary<string, Element>
            {
    
    
                {
    
    "L", new Element(){
    
    Symbol = "L", Name = "Postass", AutominNumber = 9}},
                {
    
    "Q", new Element(){
    
     Symbol = "Q", Name = "Calcium", AutominNumber = 99}},
                {
    
    "M", new Element(){
    
     Symbol = "JY", Name = "JYaoiang", AutominNumber=7924}}
            };
        }

Dictionary add value

public static void IterateDictionary()
        {
    
    
            Dictionary<string, Element> element = BuildDic();
 foreach(KeyValuePair<string, Element> keyValue in element)
            {
    
    
                Element ele = keyValue.Value;
                Console.WriteLine(string.Format("Key={0}; Values={0};{1};{2}", keyValue.Key, ele.Symbol, ele.Name, ele.AutominNumber));
            }
        }
 public static Dictionary<string, Element> BuildDictionary()
        {
    
    
 var elements = new Dictionary<string, Element>();
            AddDictionary(elements, "L", "LLL", 9);
            AddDictionary(elements, "J", "LJLHHH", 19);
            AddDictionary(elements, "A", "ABABABA", 20);
 return elements;
        }
 public static void AddDictionary(Dictionary<string, Element> elements, string symbol, string name, int num)
        {
    
    
            Element ele = new Element()
            {
    
    
                Symbol = symbol,
                Name = name,
                AutominNumber = num
            };
            elements.Add(key: symbol, value: ele);
        }

ContainsKey method and Item[] property

public static void FindDictionary(string symbol)
        {
    
    
            Dictionary<string, Element> elements = BuildDictionary();
 if (elements.ContainsKey(symbol))
            {
    
    
                Element ele = elements[symbol];
                Console.WriteLine("Found: " + ele.Name);
            }
 else
            {
    
    
                Console.WriteLine("Not found " + symbol);
            }
        }

TryGetValue method

public static void FindDictionaryOfTryGetValue(string symbol)
        {
    
    
            Dictionary<string, Element> elements = BuildDictionary();
            Element ele = null;
 if(elements.TryGetValue(symbol, out ele))
            {
    
    
                Console.WriteLine("Found: " + ele.Name);
            }
 else
            {
    
    
                Console.WriteLine("Not found " + symbol);
            }
        }

Here we explain the common usage methods of Dictionary. Here is a long-winded sentence. I don’t know if you pay attention to the Add method and TryAdd method when using Dictionary. What is the difference between these two methods?
We all know that when adding a key value to the Dictionary, the key cannot be repeated. If you use the Add method to add a duplicate key, the program will report an error. To avoid this problem, you can use the TryAdd method. When adding duplicate key values, this method will return false to avoid such problems.

ConcurrentDictionary

In .NET Framework 4and later, System.Collections.Concurrentcollections in namespaces provide efficient thread-safe operations for accessing collection items from multiple threads.
When multiple threads access collection items, you should use System.Collections.Concurrentthe classes in the namespace instead of using System.Collections.Genericthe classes in the System.Collections namespace.
System.Collections.ConcurrentClasses in the namespace: BlockingCollection, ConcurrentDictionary<TKey, TValue>、ConcurrentQueue<T>、ConcurrentStack<T>.
System.CollectionsClasses in a namespace do not store elements as specially typed objects, but as objectobjects of type.
ConcurrentDictionaryThe usage is Dictionarysimilar to and will not be explained in detail here. But ConcurrentDictionaryonly TryAddmethod Dictionarycan be used instead of Addand TryAddmethod.

Dictionary and ConcurrentDictionary multithreading

After taking everyone to know Dictionaryand ConcurrentDictionary, let's return to the topic and see how the two are used in multi-threading.
code show as below:

ConcurrentDictionary<int, string> keys = new ConcurrentDictionary<int, string>();
keys.TryAdd(1, "LL");
keys.TryAdd(2, "LL");
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "OJ");
dic.TryAdd(2, "R");
Stopwatch stopwatch = new Stopwatch();
#region 写入
stopwatch.Start();
Parallel.For(0, 10000000, i =>
{
    
    
 lock (dic)
    {
    
    
        dic[i] = new Random().Next(100, 99999).ToString();
    }
});
stopwatch.Stop();
Console.WriteLine("Dictionary加锁写入花费时间:{0}", stopwatch.Elapsed);
stopwatch.Restart();
Parallel.For(0, 10000000, i =>
{
    
    
    keys[i] = new Random().Next(100, 99999).ToString();
});
stopwatch.Stop();
Console.WriteLine("ConcurrentDictionary加锁写入花费时间:{0}", stopwatch.Elapsed);
#endregion
#region 读取
string result = string.Empty;
stopwatch.Restart();
Parallel.For(0, 10000000, i =>
{
    
    
 lock (dic)
    {
    
    
        result = dic[i];
    }
});
stopwatch.Stop();
Console.WriteLine("Dictionary加锁读取花费时间:{0}", stopwatch.Elapsed);
stopwatch.Restart();
Parallel.For(0, 10000000, i =>
{
    
    
    result = keys[i];
});
stopwatch.Stop();
Console.WriteLine("ConcurrentDictionary加锁读取花费时间:{0}", stopwatch.Elapsed);
#endregion
Console.ReadLine();

v
​

It can be found that under multi-threading, the added lockwrite Dictionaryperformance is ConconcurrentDictionarybetter than the written performance, and the performance of reading data ConcurrentDictionary is better.
When we increase the written data to 20000000, ConcurrentDictionarythe write performance is obviously Dictionaryworse than the performance, but the read performance ConcurrentDictionaryis better.

edit

When we increase the written data to 2000000, ConcurrentDictionarythe write performance is still Dictionaryworse than the performance, but the read performance ConcurrentDictionaryis better.

edit

In summary, after comparing the two, ConcurrentDictionarythe read performance is better and Dictionarythe write performance is better.
As for the specific reason, I will explain it in depth at that time. This article roughly ends here, and we will see you in the next article.

Supongo que te gusta

Origin blog.csdn.net/shanniuliqingming/article/details/132218309
Recomendado
Clasificación