刚才想了半天文章应该起什么名字,最后决定起名为《线程安全使用》,线程安全这个词很难理解,感觉就像托管这词一样,但是托管翻译成英文是managed,我通常把他翻译成被管理,这样就好理解多了,线程安全也是一样,可以理解为可以被多个线程同时使用的集合,而且同时使用的时候是该集合的值是准确的。
MSDN将在System.Collections.Concurrent命名空间下的集合,都称为线程安全的集合。
下面举一个使用线程安全集合的例子,使用的是BlockingCollection,个人觉得这个集合是够用了,其他集合和这个集合基本上大同小异,没什么大区别。但是根据官方解释ConcurrentBag是适用于快速删除和添加,具体为什么他适用,而BlockingCollection不适用,我也没找到原因。
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ParallelConsole { class Program { //定义集合大小为51个,也可以不定义大小 static BlockingCollection<int> blocking = new BlockingCollection<int>(51); static void Main(string[] args) { blocking = new BlockingCollection<int>(); Console.WriteLine("当前blocking为:" + blocking.IsCompleted + "设置了集合大小count一样是0,blocking.Count:" + blocking.Count()); //当前线程标识 Console.WriteLine(Thread.CurrentThread.GetHashCode()); for (int i = 0; i < 3; i++) { ////如果添加到第3个,就设置添加完成,这时在添加就会抛异常 //if (i == 3) //{ // blocking.CompleteAdding(); //} Action<object> action = new Action<object>(run); Task task = new Task(action,i); task.RunSynchronously(); } Console.WriteLine("设置添加完成前:" + blocking.IsAddingCompleted); //设置添加完成后 blocking.CompleteAdding(); Console.WriteLine("设置添加完成后:" + blocking.IsAddingCompleted); #region 同步取 取3个 //for (int i = 0; i < 3; i++) //{ // Action actionTake = new Action(take); // actionTake(); //} #endregion //并发读取 #region 并发步取 取3个 //blocking.IsCompleted 只有当集合被添加进内容,然后又都被取光了以后,他才会等于ture,否则都是false //当IsCompleted为ture时,就不能再取了否则会抛异常 //同时取,结果是 //blocking:0 //blocking:2 //blocking:1 if (!blocking.IsCompleted)//如果集合没取光 { Action actionTake2 = new Action(take); Parallel.Invoke(actionTake2, actionTake2, actionTake2); } #endregion Console.WriteLine("当前blocking为:" + blocking.IsCompleted + ",blocking数量为:" + blocking.Count()); //数据被取光了以后, blocking.Count()为0 Console.Read(); } public static void take() { //同步取,blocking.Count()会真实的表现,而异步取,Count是不准确的,因为我取count的时候,可能集合已经又被取出数据了,测试10次肯定会出现不真实的情况 Console.WriteLine("blocking:" + blocking.Take() + ",blocking数量为:" + blocking.Count()); } public static void run(object i) { int currentI = int.Parse(i.ToString()); blocking.TryAdd(currentI); } } }