C#多线程并发处理

540 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情 

概括

在实际处理业务中,我们经常要面临并发的问题。C#提供了多种线程安全的数据结构。那么下面我们将详细的介绍C#线程安全的数据结构。
在.Net framework4.0中引入system.collections.concurrent命名空间,该空间中包含以下数据结构:

  • concurrentqueue
  • concurrentdictionary
  • concurrentstack
  • concurrentbag
  • blockingcollect

ConcurrentQueue

队列,该集合使用了原子比较和交换,已经spinwait来保持线程安全。实现了一个FIFO集合,元素的出队列和入队列的顺序是一致的。

  • enqueue() 向队列中加入元素
  • trydequeue() 去除队列中的第一个元素(此时,队列中不再包含该元素)
  • tyrpeek() 取得队列中的第一个元素(此时,队列中还包含该元素)

conncurrentstatck

本类型没有加入任何的锁机制,仅仅使用了CAS操作。本类型是先入后出,和queue的先入先出相反。

  • push 向集合中添加一个元素
  • pushrange 向集合中添加一个元素
  • trypop 出栈,即从集合中获取一个元素
  • tyrpoprange 出栈,即从集合中获取一个元素
  • trypeek 检查元素

conncurrentdictionary

从名字可以看出来,这是一个线程安全的字典。对本字典的读操作没有加锁,但是写操作是加锁的。
conncurreentdictionary和dictionary很多操作都是相同的。但是多了一些方法

  • tryAdd 添加item到字典中去
  • TryUpdate 更新字典的key的value
  • AddOrUpdate 存在则更新,不存在则添加
  • GetOrAdd 存在则获取值,不存在则添加该key

concurrentbag

本类型是一个支持重复元素的无序集合,针对多线程的操作进行了优化。每个线程产生和消费自己的数据,极少数的和其他的线程产生交互(若需要使用交互的操作,那么必须自己加锁)

  • add() 添加元素到集合中去
  • trypeek() 检查元素
  • trytake() 从集合中获取元素

blockingcollection

该集合是线程安全的管道类,当我们面对的场景需要使用管道的时候,可以考虑使用该类。

  • 实现制造者-使用者模式
  • 通过多线程并发添加或获取数据
  • 集合为孔或者已满时通过插入和移除操作进行阻塞
  • 使用取消标记执行取消操作
    bolckingcollection支持限制和阻塞。 限制意味着可以设置集合的最大容量。
    限制在某些情况中很重要,因为它使你能够控制内存中的集合的最大大小,并可阻止制造线程移动到离使用线程前方太远的位置。 多个线程或任务可同时向集合添加项,如果集合达到其指定最大容量,则制造线程将发生阻塞,直到移除集合中的某个项。
    多个使用者可以同时移除项,如果集合变空,则使用线程将发生阻塞,直到制造者添加某个项。