zoukankan      html  css  js  c++  java
  • 安全字典ConcurrentDictionary的一个使用误区ContainsKey

    ConcurrentDictionary的ContainsKey 保证了多线程读取、写入没问题,线程安全。但是并不能保证Key 重复 。这里多线程的时候,Key可能重复导致Add失败,请优先使用 AddOrUpdate 。

    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Diagnostics;
    using System.Reflection;
    
    namespace MulThreadTest
    {
    
     //下面的示范是一个并发插入错误的写法。
    ///方案1:加锁--lock (ReaderWriterLockSlim);方案2:使用TryAddOrUpdate
        class MainClass
        {
            public static void Main (string[] args)
            {
    
        
                var dic = new ConcurrentDictionary<int,int> ();
    
    
                for (int i = 0; i < 10; i++) {
                    
                    var th = new Thread (new ParameterizedThreadStart ((state) => {
    
                        var num = DoHelper.Instance.SayHello ();
    
                        if (dic.ContainsKey (num)) {
                            dic.AddOrUpdate (num, num, (m, n) => {
                                return n;
                            });
                            Console.WriteLine ("AddOrUpdate: " + num.ToString ());
    
                        } else {
                            var addRes = dic.TryAdd (num, num);
    
                            if (false == addRes) {
                                Console.WriteLine ("Error add. num exits");
                            }
                        }
                    }));    
    
    
                    th.Start (i);
                }
    
                Console.ReadKey ();
    
            }
    
    
    
    
        }
    
    
    
        public class DoHelper
        {
    
            public static DoHelper Instance = new DoHelper ();
    
            public int SayHello ()
            {
                 
                var num = new Random (DateTime.Now.Millisecond).Next ();
    
                return num;
                 
            }
        
        }
    }

    加锁:

     1 using System;
     2 using System.Collections.Concurrent;
     3 using System.Threading;
     4 using System.Threading.Tasks;
     5 using System.Diagnostics;
     6 using System.Reflection;
     7 
     8 namespace MulThreadTest
     9 {
    10     class MainClass
    11     {
    12         public static void Main (string[] args)
    13         {
    14 
    15              
    16             var dic = new ConcurrentDictionary<int,int> ();
    17 
    18             var    _locker = new ReaderWriterLockSlim ();
    19 
    20             for (int i = 0; i < 5; i++) {
    21                 
    22                 var th = new Thread (new ParameterizedThreadStart ((state) => {
    23 
    24 
    25                     for (int yy = 0; yy < 20; yy++) {
    26                         
    27                     
    28                         var num = DoHelper.Instance.SayHello ();
    29 
    30                     
    31                         _locker.TryEnterWriteLock (TimeSpan.FromSeconds (10));
    32                      
    33 
    34                         if (dic.ContainsKey (num)) {
    35                             dic.AddOrUpdate (num, num, (m, n) => {
    36                                 return n;
    37                             });
    38                             Console.WriteLine ("AddOrUpdate: " + num.ToString ());
    39 
    40                         } else {
    41                             var addRes = dic.TryAdd (num, num);
    42 
    43 
    44 
    45                             if (false == addRes) {
    46                                 throw new Exception ("Error add. num exits:" + num.ToString ());
    47                             } else {
    48                                 Console.WriteLine ("TryAdd: " + num.ToString ());
    49                             }
    50                         }
    51 
    52                         _locker.ExitWriteLock ();
    53 
    54                     
    55                     }
    56 
    57 
    58 
    59                 }));    
    60 
    61 
    62                 th.Start (i);
    63             }
    64 
    65              
    66 
    67             Console.ReadKey ();
    68 
    69         }
    70 
    71 
    72 
    73 
    74     }
    75 
    76 
    77 
    78     public class DoHelper
    79     {
    80 
    81         public static DoHelper Instance = new DoHelper ();
    82 
    83         public int SayHello ()
    84         {
    85              
    86             var num = new Random (DateTime.Now.Millisecond).Next ();
    87 
    88             return num;
    89              
    90         }
    91     
    92     }
    93 }
    View Code

    AddOrUpdate:

     1 using System;
     2 using System.Collections.Concurrent;
     3 using System.Threading;
     4 using System.Threading.Tasks;
     5 using System.Diagnostics;
     6 using System.Reflection;
     7 
     8 namespace MulThreadTest
     9 {
    10     class MainClass
    11     {
    12         public static void Main (string[] args)
    13         {
    14 
    15              
    16             var dic = new ConcurrentDictionary<int,int> ();
    17 
    18              
    19 
    20             for (int i = 0; i < 5; i++) {
    21                 
    22                 var th = new Thread (new ParameterizedThreadStart ((state) => {
    23 
    24 
    25                     for (int yy = 0; yy < 10; yy++) {
    26                         
    27                     
    28                         var num = DoHelper.Instance.SayHello ();
    29 
    30 
    31                             dic.AddOrUpdate (num, num, (key, old) => {
    32                                 //your update logic
    33                                 return old;
    34                             });
    35                          
    36 
    37                         Console.WriteLine ("AddOrUpdate: "+num);
    38 
    39                     
    40                     }
    41 
    42 
    43 
    44                 }));    
    45 
    46 
    47                 th.Start (i);
    48             }
    49 
    50              
    51 
    52             Console.ReadKey ();
    53 
    54         }
    55 
    56 
    57 
    58 
    59     }
    60 
    61 
    62 
    63     public class DoHelper
    64     {
    65 
    66         public static DoHelper Instance = new DoHelper ();
    67 
    68         public int SayHello ()
    69         {
    70              
    71             var num = new Random (DateTime.Now.Millisecond).Next ();
    72 
    73             return num;
    74              
    75         }
    76     
    77     }
    78 }
    View Code

    参考:

    https://referencesource.microsoft.com/#mscorlib/system/Collections/Concurrent/ConcurrentDictionary.cs,4d0f4ac22dbeaf08


    using System;using System.Collections.Concurrent;using System.Threading;using System.Threading.Tasks;using System.Diagnostics;using System.Reflection;
    namespace MulThreadTest{class MainClass{public static void Main (string[] args){
     var dic = new ConcurrentDictionary<int,int> ();
     
    for (int i = 0; i < 5; i++) {var th = new Thread (new ParameterizedThreadStart ((state) => {

    for (int yy = 0; yy < 10; yy++) {var num = DoHelper.Instance.SayHello ();

    dic.AddOrUpdate (num, num, (key, old) => {    //your update logicreturn old;}); 
    Console.WriteLine ("AddOrUpdate: "+num);
    }


    }));

    th.Start (i);}
     
    Console.ReadKey ();
    }



    }


    public class DoHelper{
    public static DoHelper Instance = new DoHelper ();
    public int SayHello (){             var num = new Random (DateTime.Now.Millisecond).Next ();
    return num; }}}

  • 相关阅读:
    SnagIt 9-12 注册码
    【工具推荐】LICEcap –GIF 屏幕录制工具
    linux笔记一(基础命令)
    C#性能优化:延迟初始化Lazy<T>
    CSS3实现漂亮ToolTips
    mysql数据库sql优化
    精简代码,为网站减负的十大建议
    10个简单步骤,完全理解SQL
    13个mysql数据库的实用SQL小技巧
    MyBatis源码解读(二)
  • 原文地址:https://www.cnblogs.com/micro-chen/p/14713548.html
Copyright © 2011-2022 走看看