线程安全的集合所在的命名空间 using System.Collections.Concurrent;
Concurrent意思是并发的,并行的。反义是sequential(顺序的),线程安全的意思就是多线程中的同步
System.Collections.Concurrent 命名空间
System.Collections.Concurrent
命名空间提供多个线程安全集合类。当有多个线程并发访问集合时,应使用这些类代替 System.Collections 和 System.Collections.Generic 命名空间中的对应类型。 但是,不保证通过扩展方法或通过显式接口实现访问集合对象是线程安全的,可能需要由调用方进行同步。
类
BlockingCollection<T> | 为实现 IProducerConsumerCollection<T> 的线程安全集合提供阻塞和限制功能。 |
ConcurrentBag<T> | 表示对象的线程安全的无序集合。 |
ConcurrentDictionary<TKey,TValue> | 表示可由多个线程同时访问的键/值对的线程安全集合。 |
ConcurrentQueue<T> | 表示线程安全的先进先出 (FIFO) 集合。 |
ConcurrentStack<T> | 表示线程安全的后进先出 (LIFO) 集合。 |
OrderablePartitioner<TSource> | 表示将可排序数据源拆分为多个分区的特定方式。 |
Partitioner | 提供针对数组、列表和可枚举项的常见分区策略。 |
Partitioner<TSource> | 表示将数据源拆分为多个分区的特定方式。 |
接口
IProducerConsumerCollection<T> | 定义供制造者/使用者用来操作线程安全集合的方法。 此接口提供一个统一的表示(为生产者/消费者集合),从而更高级别抽象如 BlockingCollection<T> 可以使用集合作为基础的存储机制。 |
枚举
EnumerablePartitionerOptions | 指定控制分区程序的缓冲行为的选项。 |
参考微软官方文档:
https://docs.microsoft.com/zh-cn/dotnet/api/system.collections.concurrent?view=netframework-4.5
参考源代码(类BlockingCollection<T>)
一、示例:BlockingCollection<T> ,该类与队列ConcurrentQueue<T>类似。
源程序:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadSafeCollectionDemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("测试阻塞集合BlockingCollection的添加【Add】和移除【Take】...");
Task task = AddTakeBlockingCollectionAsync();
Task.WaitAll(task);
Console.WriteLine("下面测试阻塞集合BlockingCollection的尝试移除【TryTake】...");
TryTakeBlockingCollection();
Console.ReadLine();
}
/// <summary>
/// 阻塞集合BlockingCollection的Add(添加)和Take(移除):生产者【添加元素】、消费者【移除元素】线程安全同时操作
/// </summary>
/// <returns></returns>
static async Task AddTakeBlockingCollectionAsync()
{
using (BlockingCollection<int> blockingCollection = new BlockingCollection<int>())
{
//生产者
Task taskProducer = Task.Run(() =>
{
//添加一个元素
blockingCollection.Add(1);
blockingCollection.Add(2);
blockingCollection.Add(3);
//结束添加元素:集合已标记为完成添加。CompleteAdding()方法会导致Take()方法出现移除操作异常
blockingCollection.CompleteAdding();
});
//消费者
Task taskConsumer = Task.Factory.StartNew(() =>
{
try
{
while (true)
{
//移除一个元素,并返回这个移除的元素
int removeItem = blockingCollection.Take();
Console.WriteLine(removeItem);
}
}
catch (Exception ex)
{
Console.WriteLine($"移除项出现异常:{ex.Message}");
}
});
await Task.WhenAll(taskProducer, taskConsumer);
}
}
/// <summary>
/// 尝试移除阻塞集合BlockingCollection中的元素
/// </summary>
static void TryTakeBlockingCollection()
{
using (BlockingCollection<int> bc = new BlockingCollection<int>())
{
for (int i = 0; i < 1000; i++)
{
bc.Add(i);
}
Console.WriteLine($"是否完成添加:【{bc.IsAddingCompleted}】");
bc.CompleteAdding();//标记集合已经完成添加
Console.WriteLine($"是否完成添加:【{bc.IsAddingCompleted}】");
int outerSum = 0;
Action action = new Action(() =>
{
int localItem;
int sum = 0;
while (bc.TryTake(out localItem))
{
sum += localItem;
}
Interlocked.Add(ref outerSum, sum);
Console.WriteLine($"求和Sum={sum},当前替换:【{outerSum}】");
});
//并行操作:三个委托同时执行
//相当于 将数组求和 分 三小部分数组 分别求和,最后合并
Parallel.Invoke(action, action, action);
Console.WriteLine($"此时outerSum为【{outerSum}】");
Console.WriteLine($"此时集合已完成添加并且集合为空:【{bc.IsCompleted}】");
}
}
}
}
程序运行如图: