Cra*_*rge 6 parallel-processing .net-4.0 task-parallel-library
我试图执行以下代码,并在尝试将数组值分配给列表时不断获得索引超出范围异常: -
int[] array = new int[1000000];
for (int i = 0; i < array.Length; i++)
{
array[i] = i;
}
List<int> list = new List<int>();
Parallel.For(0, array.Length, i => list.Add(array[i]));
Run Code Online (Sandbox Code Playgroud)
我在这里做错了吗?我知道这个过程是无序/异步的,但为什么"i"得到的值高于"array.Length"的值?
Gab*_*abe 18
问题是你无法List.Add()在多个线程上同时调用.如果需要线程安全的集合,请参阅System.Collections.Concurrent命名空间.
如果中断到调试时,你会得到一个异常,你会看到,i是不是大于array.Length,而是改为2的幂是大大低于array.Length.会发生什么是List从一个像4个元素的空数组开始.每当您向一个数组已满的列表中添加一个元素时,它就会创建一个长度是旧数组长度两倍的数组,将旧元素复制到该数组,并存储新数组.
现在让我们说你的列表最多包含31个元素(意味着它有一个空格),两个线程尝试添加第32个元素.他们都会像这样执行代码:
if (_size == _items.Length)
{
EnsureCapacity(_size + 1);
}
_items[_size++] = item;
Run Code Online (Sandbox Code Playgroud)
首先,他们都会看到_size(31)不是_items.Length(32),所以他们都执行_size++.第一个线程将获得31(第32件正常指数),并更改_size为32第二个线程将获得32并尝试指标_items[32],它给你的例外,因为它试图访问一个32个元素的数组的第33个元素.