携手创作,共同成长!这是我参与「掘金日新计划 · 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支持限制和阻塞。 限制意味着可以设置集合的最大容量。
限制在某些情况中很重要,因为它使你能够控制内存中的集合的最大大小,并可阻止制造线程移动到离使用线程前方太远的位置。 多个线程或任务可同时向集合添加项,如果集合达到其指定最大容量,则制造线程将发生阻塞,直到移除集合中的某个项。
多个使用者可以同时移除项,如果集合变空,则使用线程将发生阻塞,直到制造者添加某个项。