2015-09-05 4 views
0

Допустим, мы получили две нити работает, первый один собирается быть перечисляя список, что-то вродеЧто произойдет, если экземпляр списка будет заменен во время перечисления?

foreach(int a in someList) 
{ 
    //Do something 
    //Thread 2 comes in 
} 

, а затем нить 2 присваивает новый экземпляр «someList»

someList = new List<int>(); 

Question1 : Что будет с thread1? Изменит ли он исключение или продолжит перечисление старого экземпляра?
Вопрос2: Существует ли опасность того, что «старый» список получит мусор, собранный до завершения перечисления? Поскольку ничто не ссылается на этот старый список, кроме перечислителя.

+1

Напишите код и начните тестирование? –

ответ

1

Предпринимает GetEnumerator на someList и получает таким образом объект типа IEnumerator. Этот объект запоминает исходный список и читает элементы из него один за другим.

Если теперь назначить новую вещь someList, то:

  • вы только переназначить переменную, она будет не уничтожить старый список и не изменится старый список
  • без исключений будут выброшены из-за того, что содержание старого списка составляет не изменено
  • до тех пор, пока оно существует (-> до конца foreach или break), IEnumerator по-прежнему будет исправлять mber старый список и считаны из этого
  • Еогеасп держит IEnumerator, IEnumerator держит старый список, ничего не будет GC'ed

Доказательство:

using System; 
using System.Collections.Generic; 

static void Main() 
{ 
    var list = new List<int>{ 1,2,3,4,5}; 
    foreach(var x in list) // foreach grabs old list and keeps it 
    { 
     Console.WriteLine(x); 
     list = new List<int>{9,9,9}; // replace the whole list 
    } 
} 

выход:

1 
2 
3 
4 
5 

Выше пример является одноточечным и ведет себя как описано. Изменение этого на многопоточность не ухудшит ситуацию, потому что foreach считывает переменную и запоминает экземпляр только один раз, поэтому в многопоточном дизайне, даже если вы не добавляете блокировки и не оставляете расы, в худшем случае будет либо захватить старый список, или перейти к новому списку, но никогда не оба.

0

Вопрос 1: Если память хранится правильно, это вызовет исключение.

Вопрос 2: Возможно, но это не должно иметь значения, поскольку в любом случае нужно исключать исключение.

Оказалось, что вышесказанное является правильным только в том случае, если вы изменяете список, мой плохой.

+0

Я думаю, вы думаете о исключении параллельной модификации, но в этом случае список не изменяется, а только ссылка. – 31eee384

+0

Полезно знать! :) – Phixle

Смежные вопросы