如何解决C#字典的线程安全问题

avatar
作者
筋斗云
阅读量:0

1、非线程安全举例

  Dictionary<int, int> dic = new Dictionary<int, int>();     private void TestAddNotSafe1()         {             while (true)             {                 for (int i = 0; i < 1000000; i++)                 {                     if (dic.ContainsKey(i) == false)                     {                         dic.Add(i, i);                     }                     Thread.Sleep(1);                 }                 break;             }         }          private void TestAddNotSafe2()         {             while (true)             {                 for (int i = 0; i < 1000000; i++)                 {                     if (dic.ContainsKey(i) == false)                     {                         dic.Add(i, i);                     }                     Thread.Sleep(1);                 }                 break;             }         } 
 Task.Run(TestAddNotSafe1);             Task.Run(TestAddNotSafe2); 

上述代码运行后报错,如下:
这是当前线程判断没有该键,准备添加键值对的时候,另一个线程已经添加了该键,所以提示已经添加了相同的项。
在这里插入图片描述

2、线程安全举例

为了解决上面的问题,需要使用一个线程安全的字典,

ConcurrentDictionary<int, int> concurrentDictionary = new ConcurrentDictionary<int, int>();           private void TestAddSafe1()         {             while (true)             {                 for (int i = 0; i < 1000000; i++)                 {                     if (concurrentDictionary.ContainsKey(i) == false)                     {                         if (concurrentDictionary.TryAdd(i, i))                         {                          }                         else                         {                             MessageBox.Show("错误1");                         }                     }                     Thread.Sleep(1);                 }                 break;             }         }          private void TestAddSafe2()         {             while (true)             {                 for (int i = 0; i < 1000000; i++)                 {                     if (concurrentDictionary.ContainsKey(i) == false)                     {                         if (concurrentDictionary.TryAdd(i, i))                         {                          }                         else                         {                             MessageBox.Show("错误2");                         }                     }                     Thread.Sleep(1);                 }                 break;             }         } 
   Task.Run(TestAddSafe1);             Task.Run(TestAddSafe2); 

运行后弹出窗体,提示“错误1”或者“错误2”,但是软件没有崩溃,这是因为TryAdd方法调用返回了false,所以线程安全字典的好处是不会导致软件崩溃,添加值失败只会返回false而已。
在这里插入图片描述

总结:

对于字典的线程安全问题,除了TryAdd方法外还有TryRemove、TryUpdate方法。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!