• ConcurrentDictionary测试


    经过测试发现,多线程操作都是安全的。甚至包括在遍历的时候,进行删除操作

    https://github.com/ChuckTest/ConcurrentTest

     class Program
        {
            private static readonly ConcurrentDictionary<int, int> Dictionary = new ConcurrentDictionary<int, int>();
            private static readonly List<string> AddSuccessfully = new List<string>();
            private static readonly List<string> RemoveSuccessfully = new List<string>();
            private static readonly List<string> IterateString = new List<string>();
            private static int _tryRemoveCount;
            private static readonly Random Random = new Random();
            static void Main(string[] args)
            {
                try
                {
                    int j = 0;
                    for (int i = 1; i <= 12; i++)
                    {
                        j++;
                        Thread thread;
                        if (j == 1)
                        {
                            thread = new Thread(DoTask1);
                        }
                        else if(j == 2)
                        {
                            thread = new Thread(DoTask2);
                        }
                        else if (j == 3)
                        {
                            thread = new Thread(DoTask3);
                            j = 0;
                        }
                        else
                        {
                            throw new Exception();
                        }
                        thread.IsBackground = false;
                        thread.Start(i);
                    }
    
                    Console.WriteLine("======");
                    int timeout = 0;
                    while (AddSuccessfully.Count != 100)
                    {
                        timeout++;
                        Thread.Sleep(1000);
                        if (timeout > 5)
                        {
                            break;
                        }
                    }
                    
                    timeout = 0;
                    while (_tryRemoveCount != 5)
                    {
                        timeout++;
                        Thread.Sleep(1000);
                        if (timeout > 5)
                        {
                            break;
                        }
                    }
    
                    Console.WriteLine($"addSuccessfully.Count = {AddSuccessfully.Count}");
                    foreach (var item in AddSuccessfully)
                    {
                        Console.WriteLine(item);
                    }
    
                    Console.WriteLine($"removeSuccessfully.Count = {RemoveSuccessfully.Count}");
                    foreach (var item in RemoveSuccessfully)
                    {
                        Console.WriteLine(item);
                    }
    
                    Console.WriteLine($"IterateString.Count = {IterateString.Count}");
                    foreach (var item in IterateString)
                    {
                        Console.WriteLine(item);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                finally
                {
                    Console.ReadLine();
                }
            }
    
            public static void DoTask1(object obj)
            {
                Console.WriteLine($"DoTask1 with {obj} Thread id = {Thread.CurrentThread.ManagedThreadId}");
                for (int i = 0; i < 100; i++)
                {
                    var flag = Dictionary.TryAdd(i,i);
                    if (flag)
                    {
                        AddSuccessfully.Add($"DoTask1 with {obj} add {i} successfully {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
                        //Console.WriteLine();
                    }
                    Thread.Sleep(1);
                }
            }
    
            public static void DoTask2(object obj)
            {
                _tryRemoveCount++;
                Console.WriteLine(
                    $"DoTask2 with {obj} Thread id = {Thread.CurrentThread.ManagedThreadId}, count = {Dictionary.Count}");
                var toRemove = Random.Next(0, 100);
                for (int i = 0; i < 100; i++)
                {
                    var flag = Dictionary.TryRemove(toRemove, out _);
                    if (flag)
                    {
                        RemoveSuccessfully.Add($"DoTask2 with {obj} remove {toRemove} successfully. {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
                    }
                    Thread.Sleep(1);
                }
            }
    
            public static void DoTask3(object obj)
            {
                _tryRemoveCount++;
                Console.WriteLine(
                    $"DoTask3 with {obj} Thread id = {Thread.CurrentThread.ManagedThreadId}, count = {Dictionary.Count}");
                foreach (var item in Dictionary)
                {
                    IterateString.Add($"DoTask3 with {obj} iterate {item.Key} {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
                    Thread.Sleep(2);
                }
            }
        }
    [__DynamicallyInvokable]
    public bool TryAdd(TKey key, TValue value)
    {
        if (key == null)
        {
            throw new ArgumentNullException("key");
        }
        TValue tvalue;
        return this.TryAddInternal(key, value, false, true, out tvalue);
    }
    private bool TryAddInternal(TKey key, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)
            {
                ConcurrentDictionary<TKey, TValue>.Tables tables;
                IEqualityComparer<TKey> comparer;
                bool flag;
                bool flag3;
                for (;;)
                {
                    tables = this.m_tables;
                    comparer = tables.m_comparer;
                    int hashCode = comparer.GetHashCode(key);
                    int num;
                    int num2;
                    this.GetBucketAndLockNo(hashCode, out num, out num2, tables.m_buckets.Length, tables.m_locks.Length);
                    flag = false;
                    bool flag2 = false;
                    flag3 = false;
                    try
                    {
                        if (acquireLock)
                        {
                            Monitor.Enter(tables.m_locks[num2], ref flag2);
                        }
                        if (tables != this.m_tables)
                        {
                            continue;
                        }
                        int num3 = 0;
                        ConcurrentDictionary<TKey, TValue>.Node node = null;
                        for (ConcurrentDictionary<TKey, TValue>.Node node2 = tables.m_buckets[num]; node2 != null; node2 = node2.m_next)
                        {
                            if (comparer.Equals(node2.m_key, key))
                            {
                                if (updateIfExists)
                                {
                                    if (ConcurrentDictionary<TKey, TValue>.s_isValueWriteAtomic)
                                    {
                                        node2.m_value = value;
                                    }
                                    else
                                    {
                                        ConcurrentDictionary<TKey, TValue>.Node node3 = new ConcurrentDictionary<TKey, TValue>.Node(node2.m_key, value, hashCode, node2.m_next);
                                        if (node == null)
                                        {
                                            tables.m_buckets[num] = node3;
                                        }
                                        else
                                        {
                                            node.m_next = node3;
                                        }
                                    }
                                    resultingValue = value;
                                }
                                else
                                {
                                    resultingValue = node2.m_value;
                                }
                                return false;
                            }
                            node = node2;
                            num3++;
                        }
                        if (num3 > 100 && HashHelpers.IsWellKnownEqualityComparer(comparer))
                        {
                            flag = true;
                            flag3 = true;
                        }
                        Volatile.Write<ConcurrentDictionary<TKey, TValue>.Node>(ref tables.m_buckets[num], new ConcurrentDictionary<TKey, TValue>.Node(key, value, hashCode, tables.m_buckets[num]));
                        checked
                        {
                            tables.m_countPerLock[num2]++;
                            if (tables.m_countPerLock[num2] > this.m_budget)
                            {
                                flag = true;
                            }
                        }
                    }
                    finally
                    {
                        if (flag2)
                        {
                            Monitor.Exit(tables.m_locks[num2]);
                        }
                    }
                    break;
                }
                if (flag)
                {
                    if (flag3)
                    {
                        this.GrowTable(tables, (IEqualityComparer<TKey>)HashHelpers.GetRandomizedEqualityComparer(comparer), true, this.m_keyRehashCount);
                    }
                    else
                    {
                        this.GrowTable(tables, tables.m_comparer, false, this.m_keyRehashCount);
                    }
                }
                resultingValue = value;
                return true;
            }

    [__DynamicallyInvokable]
    public bool TryAdd(TKey key, TValue value)
    {
        
    if (key == null)
        
    {
            
    throw new ArgumentNullException("key");
        
    }
        
    TValue tvalue;
        
    return this.TryAddInternal(key, value, false, true, out tvalue);
    }

  • 相关阅读:
    js之数组的方法
    js之选项卡
    js之数据类型的比较
    Android sharedUserId研究记录
    直接拿来用!最火的Android开源项目(一)
    [转]简约而不简单——Android SimpleAdapter
    [转]Android GC机制及一些调试信息
    sendToTarget 和 sendMessage 区别
    Android中内容观察者的使用---- ContentObserver类详解 (转)
    Inflate()
  • 原文地址:https://www.cnblogs.com/chucklu/p/12871201.html
Copyright © 2020-2023  润新知