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

163 篇文章 169 订阅

前言

我们在上位机软件开发过程中经常需要使用字典这个数据结构,并且经常会在多线程环境中使用字典,如果使用常规的Dictionary就会出现各种异常,本文就是详细介绍如何在多线程环境中使用字典来解决线程安全问题。

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方法。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C#中的字典(Dictionary)是线程不安全的,这意味着在多个线程同时访问和修改字典时可能会引发竞态条件(race condition)和其他线程安全问题。如果你需要在多个线程中使用字典,有几种方式可以确保线程安全性: 1. 使用锁(lock):在访问或修改字典时,使用锁来确保同时只有一个线程可以进行操作。这可以通过在代码块中使用 `lock` 关键字来实现。 ```csharp private Dictionary<string, object> myDictionary = new Dictionary<string, object>(); private object dictionaryLock = new object(); // 在访问或修改字典时使用锁 lock (dictionaryLock) { // 进行字典操作 myDictionary.Add("key", "value"); } ``` 2. 使用并发字典(ConcurrentDictionary):C#提供了一个线程安全字典实现,即`ConcurrentDictionary`。它是专门为多线程环境设计的,并提供了一组原子操作来确保线程安全性。 ```csharp private ConcurrentDictionary<string, object> myDictionary = new ConcurrentDictionary<string, object>(); // 在多个线程中访问和修改字典 myDictionary.TryAdd("key", "value"); ``` 3. 使用其他线程安全的集合类:除了字典C#还提供了其他线程安全的集合类,如`ConcurrentBag`、`ConcurrentQueue`和`ConcurrentStack`等。根据你的具体需求,选择适合的集合类来确保线程安全性。 请注意,虽然使用锁或`ConcurrentDictionary`等线程安全机制可以确保字典线程安全性,但在某些情况下可能会带来一定的性能开销。因此,根据你的应用场景和性能需求,选择合适的线程安全策略是很重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

c#上位机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值