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 }
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 }
参考:
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; }}}