C#多线程开发-使用并发集合

74612e21410848ac439d394cd11734c8.png

前言

大家好,我是阿辉。

在C#语言中当需要处理并发的场景时,就需要程序员使用最合理的数据结构。那么哪些数据结构是支持和可以在并行计算中被使用的呢。

首先这些数据结构具备可伸缩性,尽可能地避免锁(会造成多个线程的等待,防止资源竞争),同时还能提供线程安全的访问。

在.NET Framework4.0中引入了System.Collections.Concurrent命名空间,其中就包含几个数据结构。

  • ConcurrentQueus

  • ConcurrentDictionary

  • ConcurrentStack

  • ConcurrentBag

  • BlockingCollect

那么接下来,我们来看看这些支持并行计算的数据结构到底应该如何使用!

ConcurrentQueus

该集合使用了原子的比较和交换(CAS),以及SpinWait来保持线程安全。

它实现了一个先进先出(First In First Out简称FIFO)的集合。元素的出队列和加入队列的顺序是一致的。

Enqueus(): 向队列中加入元素。

TryDequeus(): 取出队列中的第一个元素,此时队里无此元素。

TryPeek(): 得到第一个元素但并不从队列中删除该元素。

ConcurrentStack

此集合在实现层也没有加入任何锁,只采用了CAS操作。

它是一个后进后出(Last In First Out,简称LIFO)集合,最近添加的元素先出去(类比为栈)。

Push()和PushRange(): 给该集合添加元素。

TryPop()和TryPopRange(): 从该集合获取元素。

TryPeek(): 检查元素。

ConcurrentBag

该集合是一个支持重复元素的无序集合,专门针对下面多个线程工作时,集合进行了优化。每个线程产生和消费自己的任务,极少与其他线程的任何交互(若需要使用交互,则必须使用锁操作)。

Add(): 添加元素。

TryPeek(): 检查元素。

TryTake(): 获取元素。

ConcurrentDictionary

是一个线程安全的字典集合。其中读操作无需使用锁,写操作需要使用锁。

该并发字典使用多个锁,在字典之上实现一个细粒度的锁模型。其中使用concurrencyLevel可以在构造函数中定义锁的数量,那么说意味着预估的线程数量将并发地更新该字典。

由于并发字典使用锁,所以一些操作需要获取该字典中的所有锁。若是在编程过程中,没有必要则不要调用下面方法:Count,IsEmpty,Keys,Values,CopyTo及ToArray。

BlockingCollection

该集合是对泛型接口IProducerConsumerCollection实现的一个高级封装。其中有很多管道场景,即当你有一些操作需要使用之前计算的结果。

BlockingCollection支持如下功能:

  • 分块

  • 调整内部集合容量

  • 取消集合操作

  • 从多个块集合中获取元素

Demo

在单线程的环境中使用通用字典与使用通用字典的性能。

使用ConcurrentDictionary
class Program
    {
        const string Item = "";
        public static string CurrentItem;
        static void Main(string[] args)
        {
            var concurrentDicrionary=new ConcurrentDictionary<int ,string>();
            var dictionary=new Dictionary<int ,string>();

            var sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < 1000000; i++)
            {
                lock(dictionary)
                {
                    dictionary[i]=Item;
                }
            }
            sw.Stop();
            Console.WriteLine("写dictionary的时间"+sw.Elapsed);

            sw.Restart();
            for (int i = 0; i < 1000000; i++)
            {
                concurrentDicrionary[i] = Item;
            }
            sw.Stop();
            Console.WriteLine("写并发集合concurrentDicrionary的时间:" + sw.Elapsed);

            sw.Restart();
            for (int i = 0; i < 1000000; i++)
            {
                lock(dictionary)
                {
                    CurrentItem = dictionary[i];
                }
            }
            sw.Stop();
            Console.WriteLine("读dictionary的时间" + sw.Elapsed);

            sw.Restart();
            for (int i = 0; i < 1000000; i++)
            {
                CurrentItem=concurrentDicrionary[i];
            }
            sw.Stop();
            Console.WriteLine("读并发集合concurrentDicrionary的时间:" + sw.Elapsed);

            Console.ReadKey();
        }
    }
d9caf48655d730e881325172dfe6097c.png

可以发现使用ConcurrentDictionary写操作比使用锁的通用字典要慢很多,而读操作则更快些。因此如果对字典需要大量的线程安全的读操作,则ConcurrentDictionary是更好的选择。

小寄语

人生短暂,我不想去追求自己看不见的,我只想抓住我能看得见的。

原创不易,给个关注。

我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发  谢谢。

a7872f9ddd32485e0a75c98339123424.png

往期推荐

C#多线程开发-线程间通讯

C#多线程开发-处理子线程中的异常

C#多线程开发-了解C#5.0 05

C#多线程开发-任务并行库04

C#多线程开发-线程池03

C#多线程开发-线程同步02

C#多线程开发-线程基础 01

a6772f628bb3f94697b460959d621506.png

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
学习C#多线程的路线可以按照以下步骤进行: 1. 先了解基本概念:开始学习之前,建议先了解多线程的基本概念和原理,包括线程、进程、并发、同步等相关概念。 2. 学习线程的创建和启动:学习如何在C#中创建和启动线程,可以使用Thread类或者Task类来实现。 3. 线程同步和互斥:学习如何在多线程环境下实现线程同步和互斥,以避免出现竞态条件和数据不一致的问题。可以学习使用锁、互斥量、信号量等机制来实现线程同步。 4. 学习线程间通信:学习如何在多线程环境下实现线程间的通信,以便线程之间能够进行数据交换和协作。可以学习使用共享内存、消息队列、事件等机制来实现线程间通信。 5. 学习线程池:学习如何使用线程池来管理和调度线程,以提高多线程应用程序的性能和效率。 6. 学习并发集合:学习如何使用并发集合来处理多线程环境下的数据共享和访问问题,包括并发队列并发字典、并发栈等。 7. 学习异步编程:学习如何使用异步编程模型(Async/Await)来实现高效的异步操作,以提高多线程应用程序的响应性和吞吐量。 8. 学习线程安全性:学习如何编写线程安全的代码,以避免出现竞态条件和数据不一致的问题。可以学习使用锁、原子操作、线程本地存储等技术来确保线程安全性。 9. 实践项目:通过实践项目来巩固所学的多线程知识,可以选择一些具有多线程需求的项目来进行实践,例如网络服务器、并发任务处理等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值