https://www.mgenware.com/blog/?p=232
ConcurrentBag<T>对于同一个线程值的添加和删除是非常快的,因为ConcurrentBag内部将数据按线程的标识而独立存储,所以一个线程从自己的数据中移除一个数据是非常快的,当然如果这个线程中没有数据,那么只能从其他线程中移除数据,此时会发生一些性能损耗从而确保线程安全! 比如从线程1中加入两个数据,在线程2中加入一个数据。那么当线程2调用TryTake时,被移除的数据肯定是线程2加入的那个数据: //+ using System.Threading.Tasks; //+ using System.Collections.Concurrent; var bag = new ConcurrentBag<string>(); var t1 = Task.Factory.StartNew(() => { bag.Add("线程1: 1"); Thread.Sleep(1000); bag.Add("线程1: 2"); foreach (var str in bag) Console.WriteLine(str); }); var t2 = Task.Factory.StartNew(() => { bag.Add("线程2: 1"); Thread.Sleep(2000); string str; bag.TryTake(out str); Console.WriteLine("线程2取出:" + str); }); Task.WaitAll(t1, t2); 输出: 线程1: 2 线程1: 1 线程2: 1 线程2取出:线程2: 1 如果在线程2(代码中的t2 Task)去掉往ConcurrentBag中添加数据的代码,那么ConcurrentBag将会从线程1的数据中删除一项元素。示例输出: 线程1: 2 线程1: 1 线程2取出:线程1: 1
ConcurrentBag<T>对于同一个线程值的添加和删除是非常快的,因为ConcurrentBag内部将数据按线程的标识而独立存储,所以一个线程从自己的数据中移除一个数据是非常快的,当然如果这个线程中没有数据,那么只能从其他线程中移除数据,此时会发生一些性能损耗从而确保线程安全!
比如从线程1中加入两个数据,在线程2中加入一个数据。那么当线程2调用TryTake时,被移除的数据肯定是线程2加入的那个数据:
//+ using System.Threading.Tasks;
//+ using System.Collections.Concurrent;
var bag =newConcurrentBag<string>();
var t1 =Task.Factory.StartNew(() =>
{
bag.Add("线程1: 1");
Thread.Sleep(1000);
bag.Add("线程1: 2");
foreach (var str in bag)
Console.WriteLine(str);
});
var t2 =Task.Factory.StartNew(() =>
{
bag.Add("线程2: 1");
Thread.Sleep(2000);
string str;
bag.TryTake(out str);
Console.WriteLine("线程2取出:"+ str);
});
Task.WaitAll(t1, t2);
输出:
线程1: 2
线程1: 1
线程2: 1
线程2取出:线程2: 1
如果在线程2(代码中的t2 Task)去掉往ConcurrentBag中添加数据的代码,那么ConcurrentBag将会从线程1的数据中删除一项元素。示例输出:
线程1: 2
线程1: 1
线程2取出:线程1: 1